Merge "Switch GCC -O flags, O3 non-debug, 01 debug." into dalvik-dev
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index b8727fe..4659f7b 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -2231,13 +2231,18 @@
   } else if ((access_flags & kAccAbstract) != 0) {
   } else {
     bool compile = verifier::MethodVerifier::IsCandidateForCompilation(code_item, access_flags);
+#ifdef ART_SEA_IR_MODE
+    bool use_sea = Runtime::Current()->IsSeaIRMode();
+    use_sea = use_sea && (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
+    if (use_sea) compile = true;
+#endif
+
     if (compile) {
       CompilerFn compiler = compiler_;
 #ifdef ART_SEA_IR_MODE
-      bool use_sea = Runtime::Current()->IsSeaIRMode();
-      use_sea = use_sea && (std::string::npos != PrettyMethod(method_idx, dex_file).find("fibonacci"));
       if (use_sea) {
         compiler = sea_ir_compiler_;
+        LOG(INFO) << "Using SEA IR to compile..." << std::endl;
       }
 #endif
       // NOTE: if compiler declines to compile this method, it will return NULL.
diff --git a/compiler/elf_writer_test.cc b/compiler/elf_writer_test.cc
index e48806e..ffe1f72 100644
--- a/compiler/elf_writer_test.cc
+++ b/compiler/elf_writer_test.cc
@@ -62,7 +62,7 @@
 
   ASSERT_EQ(0, dlclose(dl_oat_so));
 
-  UniquePtr<File> file(OS::OpenFile(elf_filename.c_str(), false));
+  UniquePtr<File> file(OS::OpenFileForReading(elf_filename.c_str()));
   ASSERT_TRUE(file.get() != NULL);
   {
     UniquePtr<ElfFile> ef(ElfFile::Open(file.get(), false, false));
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index a40e3fc..4e9ae54 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -79,7 +79,7 @@
     dex_caches_.insert(dex_cache);
   }
 
-  UniquePtr<File> oat_file(OS::OpenFile(oat_filename.c_str(), true, false));
+  UniquePtr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str()));
   if (oat_file.get() == NULL) {
     LOG(ERROR) << "Failed to open oat file " << oat_filename << " for " << oat_location;
     return false;
@@ -145,7 +145,7 @@
   PatchOatCodeAndMethods();
   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
 
-  UniquePtr<File> image_file(OS::OpenFile(image_filename.c_str(), true));
+  UniquePtr<File> image_file(OS::CreateEmptyFile(image_filename.c_str()));
   if (image_file.get() == NULL) {
     LOG(ERROR) << "Failed to open image file " << image_filename;
     return false;
diff --git a/compiler/llvm/llvm_compilation_unit.cc b/compiler/llvm/llvm_compilation_unit.cc
index 9296fc7..aa439cc 100644
--- a/compiler/llvm/llvm_compilation_unit.cc
+++ b/compiler/llvm/llvm_compilation_unit.cc
@@ -155,7 +155,7 @@
   std::string bitcode;
   DumpBitcodeToString(bitcode);
   std::string filename(StringPrintf("%s/Art%u.bc", DumpDirectory().c_str(), cunit_id_));
-  UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+  UniquePtr<File> output(OS::CreateEmptyFile(filename.c_str()));
   output->WriteFully(bitcode.data(), bitcode.size());
   LOG(INFO) << ".bc file written successfully: " << filename;
 }
@@ -182,7 +182,7 @@
   if (kDumpELF) {
     // Dump the ELF image for debugging
     std::string filename(StringPrintf("%s/Art%u.o", DumpDirectory().c_str(), cunit_id_));
-    UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+    UniquePtr<File> output(OS::CreateEmptyFile(filename.c_str()));
     output->WriteFully(elf_object_.data(), elf_object_.size());
     LOG(INFO) << ".o file written successfully: " << filename;
   }
diff --git a/compiler/sea_ir/debug/dot_gen.h b/compiler/sea_ir/debug/dot_gen.h
index 675d83d..05d97fa 100644
--- a/compiler/sea_ir/debug/dot_gen.h
+++ b/compiler/sea_ir/debug/dot_gen.h
@@ -20,6 +20,7 @@
 #include "safe_map.h"
 #include "base/stringprintf.h"
 #include "file_output_stream.h"
+#include "os.h"
 #include "sea_ir/ir/sea.h"
 #include "sea_ir/types/type_inference.h"
 
@@ -103,7 +104,7 @@
     LOG(INFO) << "Starting to write SEA string to file.";
     DotGenerationVisitor dgv = DotGenerationVisitor(&options_, types);
     graph->Accept(&dgv);
-    art::File* file = art::OS::OpenFile(filename.c_str(), true, true);
+    art::File* file = art::OS::OpenFileReadWrite(filename.c_str());
     art::FileOutputStream fos(file);
     std::string graph_as_string = dgv.GetResult();
     graph_as_string += "}";
diff --git a/compiler/sea_ir/frontend.cc b/compiler/sea_ir/frontend.cc
index e24d07d..421c3a4 100644
--- a/compiler/sea_ir/frontend.cc
+++ b/compiler/sea_ir/frontend.cc
@@ -16,18 +16,26 @@
 
 #ifdef ART_SEA_IR_MODE
 #include <llvm/Support/Threading.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+
 #include "base/logging.h"
+#include "llvm/llvm_compilation_unit.h"
 #include "dex/portable/mir_to_gbc.h"
 #include "driver/compiler_driver.h"
-#include "leb128.h"
-#include "llvm/llvm_compilation_unit.h"
+#include "verifier/method_verifier.h"
 #include "mirror/object.h"
+#include "utils.h"
+
 #include "runtime.h"
 #include "safe_map.h"
 
 #include "sea_ir/ir/sea.h"
 #include "sea_ir/debug/dot_gen.h"
 #include "sea_ir/types/types.h"
+#include "sea_ir/code_gen/code_gen.h"
+
+
 namespace art {
 
 static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler,
@@ -44,12 +52,31 @@
   //       and silencing the cpplint.py warning, I just corrected the formatting.
   VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
   sea_ir::SeaGraph* ir_graph = sea_ir::SeaGraph::GetGraph(dex_file);
-  ir_graph->CompileMethod(code_item, class_def_idx, method_idx, method_access_flags, dex_file);
+  sea_ir::CodeGenData* llvm_data =
+      ir_graph->CompileMethod(code_item, class_def_idx, method_idx, method_access_flags, dex_file);
   sea_ir::DotConversion dc;
   SafeMap<int, const sea_ir::Type*>*  types = ir_graph->ti_->GetTypeMap();
   dc.DumpSea(ir_graph, "/tmp/temp.dot", types);
   CHECK(0 && "No SEA compiled function exists yet.");
-  return NULL;
+
+  MethodReference mref(&dex_file, method_idx);
+
+  // TODO: Passing the LLVM code as string is ugly and inefficient,
+  //       but it is the way portable did it. I kept it for compatibility,
+  //       but actually it should not happen.
+  std::string llvm_code;
+  ::llvm::raw_string_ostream str_os(llvm_code);
+  ::llvm::WriteBitcodeToFile(&llvm_data->module_, str_os);
+
+  std::string symbol = "dex_";
+  symbol += MangleForJni(PrettyMethod(method_idx, dex_file));
+
+  CompiledMethod* compiled_method =  new CompiledMethod(
+                              compiler.GetInstructionSet(),
+                              llvm_code,
+                              *verifier::MethodVerifier::GetDexGcMap(mref),
+                              symbol);
+  return compiled_method;
 }
 
 CompiledMethod* SeaIrCompileOneMethod(CompilerDriver& compiler,
diff --git a/compiler/sea_ir/ir/sea.cc b/compiler/sea_ir/ir/sea.cc
index 08fe0e1..902839d 100644
--- a/compiler/sea_ir/ir/sea.cc
+++ b/compiler/sea_ir/ir/sea.cc
@@ -386,7 +386,7 @@
   scoped_table->CloseScope();
 }
 
-void SeaGraph::GenerateLLVM() {
+CodeGenData* SeaGraph::GenerateLLVM() {
   // Pass: Generate LLVM IR.
   CodeGenPrepassVisitor code_gen_prepass_visitor;
   std::cout << "Generating code..." << std::endl;
@@ -399,9 +399,11 @@
   CodeGenPostpassVisitor code_gen_postpass_visitor(code_gen_visitor.GetData());
   Accept(&code_gen_postpass_visitor);
   code_gen_postpass_visitor.Write(std::string("my_file.llvm"));
+  return code_gen_postpass_visitor.GetData();
 }
 
-void SeaGraph::CompileMethod(const art::DexFile::CodeItem* code_item, uint32_t class_def_idx,
+CodeGenData* SeaGraph::CompileMethod(
+    const art::DexFile::CodeItem* code_item, uint32_t class_def_idx,
     uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file) {
   // Two passes: Builds the intermediate structure (non-SSA) of the sea-ir for the function.
   BuildMethodSeaGraph(code_item, dex_file, class_def_idx, method_idx, method_access_flags);
@@ -420,7 +422,8 @@
   // Pass: type inference
   ti_->ComputeTypes(this);
   // Pass: Generate LLVM IR.
-  GenerateLLVM();
+  CodeGenData* cgd = GenerateLLVM();
+  return cgd;
 }
 
 void SeaGraph::ComputeDominanceFrontier() {
diff --git a/compiler/sea_ir/ir/sea.h b/compiler/sea_ir/ir/sea.h
index 0b20ed7..df420ed 100644
--- a/compiler/sea_ir/ir/sea.h
+++ b/compiler/sea_ir/ir/sea.h
@@ -37,6 +37,7 @@
 };
 
 class TypeInference;
+class CodeGenData;
 
 class Region;
 class InstructionNode;
@@ -260,7 +261,7 @@
  public:
   static SeaGraph* GetGraph(const art::DexFile&);
 
-  void CompileMethod(const art::DexFile::CodeItem* code_item, uint32_t class_def_idx,
+  CodeGenData* CompileMethod(const art::DexFile::CodeItem* code_item, uint32_t class_def_idx,
       uint32_t method_idx, uint32_t method_access_flags, const art::DexFile& dex_file);
   // Returns all regions corresponding to this SeaGraph.
   std::vector<Region*>* GetRegions() {
@@ -337,7 +338,7 @@
   void RenameAsSSA(Region* node, utils::ScopedHashtable<int, InstructionNode*>* scoped_table);
   // Generate LLVM IR for the method.
   // Precondition: ConvertToSSA().
-  void GenerateLLVM();
+  CodeGenData* GenerateLLVM();
 
   static SeaGraph graph_;
   std::vector<Region*> regions_;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 25cfda6..ceb6bf6 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -313,7 +313,7 @@
       oat_data_begin = image_writer.GetOatDataBegin();
     }
 
-    UniquePtr<File> oat_file(OS::OpenFile(oat_filename.c_str(), true, false));
+    UniquePtr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str()));
     if (oat_file.get() == NULL) {
       PLOG(ERROR) << "Failed to open ELF file: " << oat_filename;
       return false;
@@ -808,7 +808,7 @@
   UniquePtr<File> oat_file;
   bool create_file = !oat_unstripped.empty();  // as opposed to using open file descriptor
   if (create_file) {
-    oat_file.reset(OS::OpenFile(oat_unstripped.c_str(), true));
+    oat_file.reset(OS::CreateEmptyFile(oat_unstripped.c_str()));
     if (oat_location.empty()) {
       oat_location = oat_filename;
     }
@@ -1023,8 +1023,8 @@
   if (oat_unstripped != oat_stripped) {
     timings.NewSplit("dex2oat OatFile copy");
     oat_file.reset();
-    UniquePtr<File> in(OS::OpenFile(oat_unstripped.c_str(), false));
-    UniquePtr<File> out(OS::OpenFile(oat_stripped.c_str(), true));
+     UniquePtr<File> in(OS::OpenFileForReading(oat_unstripped.c_str()));
+    UniquePtr<File> out(OS::CreateEmptyFile(oat_stripped.c_str()));
     size_t buffer_size = 8192;
     UniquePtr<uint8_t> buffer(new uint8_t[buffer_size]);
     while (true) {
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 67398af..fbfdfd9 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -777,7 +777,7 @@
       os_ = saved_os;
     }
     os << "STATS:\n" << std::flush;
-    UniquePtr<File> file(OS::OpenFile(image_filename_.c_str(), false));
+    UniquePtr<File> file(OS::OpenFileForReading(image_filename_.c_str()));
     stats_.file_bytes = file->GetLength();
     size_t header_bytes = sizeof(ImageHeader);
     stats_.header_bytes = header_bytes;
diff --git a/runtime/arch/arm/portable_entrypoints_arm.S b/runtime/arch/arm/portable_entrypoints_arm.S
index f21ae28..073efdc 100644
--- a/runtime/arch/arm/portable_entrypoints_arm.S
+++ b/runtime/arch/arm/portable_entrypoints_arm.S
@@ -114,7 +114,7 @@
     .cfi_rel_offset r10, 28
     .cfi_rel_offset r11, 32
     .cfi_rel_offset lr, 36
-    sub sp, #8                        @ 2 words of space, bottom word will hold Method*
+    sub sp, #8                     @ 2 words of space, bottom word will hold Method*
     .pad #8
     .cfi_adjust_cfa_offset 8
     mov     r2, r9                 @ pass Thread::Current
@@ -156,7 +156,7 @@
     .cfi_rel_offset r10, 28
     .cfi_rel_offset r11, 32
     .cfi_rel_offset lr, 36
-    sub sp, #8                        @ 2 words of space, bottom word will hold Method*
+    sub sp, #8                     @ 2 words of space, bottom word will hold Method*
     .pad #8
     .cfi_adjust_cfa_offset 8
     mov     r1, r9                 @ pass Thread::Current
diff --git a/runtime/arch/x86/portable_entrypoints_x86.S b/runtime/arch/x86/portable_entrypoints_x86.S
index 0313d4b..24fa98b 100644
--- a/runtime/arch/x86/portable_entrypoints_x86.S
+++ b/runtime/arch/x86/portable_entrypoints_x86.S
@@ -68,13 +68,13 @@
 DEFINE_FUNCTION art_portable_proxy_invoke_handler
     // Fake callee save ref and args frame set up, note portable doesn't use callee save frames.
     // TODO: just save the registers that are needed in artPortableProxyInvokeHandler.
-    PUSH edi  // Save callee saves
+    PUSH edi                      // Save callee saves
     PUSH esi
     PUSH ebp
-    PUSH ebx  // Save args
+    PUSH ebx                      // Save args
     PUSH edx
     PUSH ecx
-    PUSH eax   // Align stack, eax will be clobbered by Method*
+    PUSH eax                      // Align stack, eax will be clobbered by Method*
     // Begin argument set up.
     PUSH esp                      // pass SP
     pushl %fs:THREAD_SELF_OFFSET  // pass Thread::Current()
@@ -90,5 +90,35 @@
     ret
 END_FUNCTION art_portable_proxy_invoke_handler
 
-UNIMPLEMENTED art_portable_resolution_trampoline
-UNIMPLEMENTED art_portable_to_interpreter_bridge
+DEFINE_FUNCTION art_portable_resolution_trampoline
+  pushl %ebp
+  movl %esp, %ebp                 // save ESP
+  subl LITERAL(8), %esp           // Align stack
+  movl 8(%ebp), %eax              // Method* called
+  leal 8(%ebp), %edx              // Method** called_addr
+  pushl %edx                      // pass called_addr
+  pushl %fs:THREAD_SELF_OFFSET    // pass thread
+  pushl %ecx                      // pass receiver
+  pushl %eax                      // pass called
+  call SYMBOL(artPortableResolutionTrampoline)
+  leave
+  cmpl LITERAL(0), %eax
+  je resolve_fail
+  jmp * %eax
+resolve_fail:
+  ret
+END_FUNCTION art_portable_resolution_trampoline
+
+DEFINE_FUNCTION art_portable_to_interpreter_bridge
+  pushl %ebp
+  movl %esp, %ebp                 // save ESP
+  subl LITERAL(12), %esp          // Align stack
+  movl 8(%ebp), %eax              // Method* called
+  leal 8(%ebp), %edx              // Method** called_addr
+  pushl %edx                      // pass called_addr
+  pushl %fs:THREAD_SELF_OFFSET    // pass thread
+  pushl %eax                      // pass called
+  call SYMBOL(artPortableToInterpreterBridge)
+  leave
+  ret
+END_FUNCTION art_quick_to_interpreter_bridge
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index bd36a6c..039e7bc 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -659,6 +659,7 @@
       CHECK_NE(&oat_file, oat_files_[i]) << oat_file.GetLocation();
     }
   }
+  VLOG(class_linker) << "Registering " << oat_file.GetLocation();
   oat_files_.push_back(&oat_file);
 }
 
@@ -694,22 +695,39 @@
   UniquePtr<OatFile> oat_file(OatFile::Open(oat_location, oat_location, NULL,
                                             !Runtime::Current()->IsCompiler()));
   if (oat_file.get() == NULL) {
+    VLOG(class_linker) << "Failed to find existing oat file at " << oat_location;
     return NULL;
   }
   Runtime* runtime = Runtime::Current();
   const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
-  if (oat_file->GetOatHeader().GetImageFileLocationOatChecksum() != image_header.GetOatChecksum()) {
+  uint32_t expected_image_oat_checksum = image_header.GetOatChecksum();
+  uint32_t actual_image_oat_checksum = oat_file->GetOatHeader().GetImageFileLocationOatChecksum();
+  if (expected_image_oat_checksum != actual_image_oat_checksum) {
+    VLOG(class_linker) << "Failed to find oat file at " << oat_location
+                       << " with expected image oat checksum of " << expected_image_oat_checksum
+                       << ", found " << actual_image_oat_checksum;
     return NULL;
   }
-  if (oat_file->GetOatHeader().GetImageFileLocationOatDataBegin()
-      != reinterpret_cast<uint32_t>(image_header.GetOatDataBegin())) {
+
+  uint32_t expected_image_oat_offset = reinterpret_cast<uint32_t>(image_header.GetOatDataBegin());
+  uint32_t actual_image_oat_offset = oat_file->GetOatHeader().GetImageFileLocationOatDataBegin();
+  if (expected_image_oat_offset != actual_image_oat_offset) {
+    VLOG(class_linker) << "Failed to find oat file at " << oat_location
+                       << " with expected image oat offset " << expected_image_oat_offset
+                       << ", found " << actual_image_oat_offset;
     return NULL;
   }
   const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
   if (oat_dex_file == NULL) {
+    VLOG(class_linker) << "Failed to find oat file at " << oat_location << " containing " << dex_location;
     return NULL;
   }
-  if (oat_dex_file->GetDexFileLocationChecksum() != dex_location_checksum) {
+  uint32_t expected_dex_checksum = dex_location_checksum;
+  uint32_t actual_dex_checksum = oat_dex_file->GetDexFileLocationChecksum();
+  if (expected_dex_checksum != actual_dex_checksum) {
+    VLOG(class_linker) << "Failed to find oat file at " << oat_location
+                       << " with expected dex checksum of " << expected_dex_checksum
+                       << ", found " << actual_dex_checksum;
     return NULL;
   }
   RegisterOatFileLocked(*oat_file.release());
@@ -722,6 +740,58 @@
   return FindOrCreateOatFileForDexLocationLocked(dex_location, oat_location);
 }
 
+class ScopedFlock {
+ public:
+  ScopedFlock() {}
+
+  bool Init(const std::string& filename) {
+    while (true) {
+      file_.reset(OS::OpenFileWithFlags(filename.c_str(), O_CREAT | O_RDWR));
+      if (file_.get() == NULL) {
+        LOG(ERROR) << "Failed to open file: " << filename;
+        return false;
+      }
+      int flock_result = TEMP_FAILURE_RETRY(flock(file_->Fd(), LOCK_EX));
+      if (flock_result != 0) {
+        PLOG(ERROR) << "Failed to lock file: " << filename;
+        return false;
+      }
+      struct stat fstat_stat;
+      int fstat_result = TEMP_FAILURE_RETRY(fstat(file_->Fd(), &fstat_stat));
+      if (fstat_result != 0) {
+        PLOG(ERROR) << "Failed to fstat: " << filename;
+        return false;
+      }
+      struct stat stat_stat;
+      int stat_result = TEMP_FAILURE_RETRY(stat(filename.c_str(), &stat_stat));
+      if (stat_result != 0) {
+        PLOG(WARNING) << "Failed to stat, will retry: " << filename;
+        // ENOENT can happen if someone racing with us unlinks the file we created so just retry.
+        continue;
+      }
+      if (fstat_stat.st_dev != stat_stat.st_dev || fstat_stat.st_ino != stat_stat.st_ino) {
+        LOG(WARNING) << "File changed while locking, will retry: " << filename;
+        continue;
+      }
+      return true;
+    }
+  }
+
+  File& GetFile() {
+    return *file_;
+  }
+
+  ~ScopedFlock() {
+    int flock_result = TEMP_FAILURE_RETRY(flock(file_->Fd(), LOCK_UN));
+    CHECK_EQ(0, flock_result);
+  }
+
+ private:
+  UniquePtr<File> file_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedFlock);
+};
+
 const DexFile* ClassLinker::FindOrCreateOatFileForDexLocationLocked(const std::string& dex_location,
                                                                     const std::string& oat_location) {
   uint32_t dex_location_checksum;
@@ -730,6 +800,17 @@
     return NULL;
   }
 
+  // We play a locking game here so that if two different processes
+  // race to generate (or worse, one tries to open a partial generated
+  // file) we will be okay. This is actually common with apps that use
+  // DexClassLoader to work around the dex method reference limit and
+  // that have a background service running in a separate process.
+  ScopedFlock scoped_flock;
+  if (!scoped_flock.Init(oat_location)) {
+    LOG(ERROR) << "Failed to open locked oat file: " << oat_location;
+    return NULL;
+  }
+
   // Check if we already have an up-to-date output file
   const DexFile* dex_file = FindDexFileInOatLocation(dex_location,
                                                      dex_location_checksum,
@@ -739,12 +820,8 @@
   }
 
   // Generate the output oat file for the dex file
-  UniquePtr<File> file(OS::OpenFile(oat_location.c_str(), true));
-  if (file.get() == NULL) {
-    LOG(ERROR) << "Failed to create oat file: " << oat_location;
-    return NULL;
-  }
-  if (!GenerateOatFile(dex_location, file->Fd(), oat_location)) {
+  VLOG(class_linker) << "Generating oat file " << oat_location << " for " << dex_location;
+  if (!GenerateOatFile(dex_location, scoped_flock.GetFile().Fd(), oat_location)) {
     LOG(ERROR) << "Failed to generate oat file: " << oat_location;
     return NULL;
   }
diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc
index e7899ec..6449493 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -64,7 +64,7 @@
   CHECK(dex_bytes.get() != NULL);
 
   // write to provided file
-  UniquePtr<File> file(OS::OpenFile(location.c_str(), true));
+  UniquePtr<File> file(OS::CreateEmptyFile(location.c_str()));
   CHECK(file.get() != NULL);
   if (!file->WriteFully(dex_bytes.get(), length)) {
     PLOG(FATAL) << "Failed to write base64 as dex file";
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 6b8c41e..52f8c81 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -23,6 +23,7 @@
 #include "mirror/art_method-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
+#include "object_utils.h"
 #include "mirror/object_array-inl.h"
 #include "mirror/proxy.h"
 #include "reflection.h"
@@ -269,7 +270,10 @@
 }
 
 void ThrowStackOverflowError(Thread* self) {
-  CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow.";
+  if (self->IsHandlingStackOverflow()) {
+      LOG(ERROR) << "Recursive stack overflow.";
+      // We don't fail here because SetStackEndForStackOverflow will print better diagnostics.
+  }
 
   if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) {
     // Remove extra entry pushed onto second stack during method tracing.
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 2b73af4..8b58cb3 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -16,7 +16,7 @@
 
 #ifndef ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
 #define ART_RUNTIME_ENTRYPOINTS_ENTRYPOINT_UTILS_H_
-
+#include "object_utils.h"
 #include "class_linker.h"
 #include "common_throws.h"
 #include "dex_file.h"
@@ -27,7 +27,7 @@
 #include "mirror/array.h"
 #include "mirror/class-inl.h"
 #include "mirror/throwable.h"
-#include "object_utils.h"
+
 #include "thread.h"
 
 namespace art {
diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
index e1ce11a..61f7440 100644
--- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
@@ -42,8 +42,10 @@
 #define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 64
 #define PORTABLE_STACK_ARG_SKIP 16
 #elif defined(__i386__)
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 4
-#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 32
+// For x86 there are no register arguments and the stack pointer will point directly to the called
+// method argument passed by the caller.
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__R1_OFFSET 0
+#define PORTABLE_CALLEE_SAVE_FRAME__REF_AND_ARGS__FRAME_SIZE 0
 #define PORTABLE_STACK_ARG_SKIP 4
 #else
 #error "Unsupported architecture"
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 392bcc5..535d540 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -15,8 +15,10 @@
  */
 
 #include "callee_save_frame.h"
+#include "common_throws.h"
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
+#include "entrypoints/entrypoint_utils.h"
 #include "interpreter/interpreter.h"
 #include "invoke_arg_array_builder.h"
 #include "mirror/art_method-inl.h"
@@ -26,6 +28,8 @@
 #include "object_utils.h"
 #include "runtime.h"
 
+
+
 namespace art {
 
 // Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
@@ -218,10 +222,11 @@
 };
 
 // Visits arguments on the stack placing them into the shadow frame.
-class BuildShadowFrameVisitor : public QuickArgumentVisitor {
+class BuildQuickShadowFrameVisitor : public QuickArgumentVisitor {
  public:
-  BuildShadowFrameVisitor(mirror::ArtMethod** sp, bool is_static, const char* shorty,
-                          uint32_t shorty_len, ShadowFrame& sf, size_t first_arg_reg) :
+  BuildQuickShadowFrameVisitor(mirror::ArtMethod** sp,
+      bool is_static, const char* shorty,
+       uint32_t shorty_len, ShadowFrame& sf, size_t first_arg_reg) :
     QuickArgumentVisitor(sp, is_static, shorty, shorty_len), sf_(sf), cur_reg_(first_arg_reg) {}
 
   virtual void Visit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -258,7 +263,7 @@
   ShadowFrame& sf_;
   size_t cur_reg_;
 
-  DISALLOW_COPY_AND_ASSIGN(BuildShadowFrameVisitor);
+  DISALLOW_COPY_AND_ASSIGN(BuildQuickShadowFrameVisitor);
 };
 
 extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Thread* self,
@@ -280,7 +285,7 @@
     ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, NULL,  // No last shadow coming from quick.
                                                   method, 0, memory));
     size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_;
-    BuildShadowFrameVisitor shadow_frame_builder(sp, mh.IsStatic(), mh.GetShorty(),
+    BuildQuickShadowFrameVisitor shadow_frame_builder(sp, mh.IsStatic(), mh.GetShorty(),
                                                  mh.GetShortyLength(),
                                                  *shadow_frame, first_arg_reg);
     shadow_frame_builder.VisitArguments();
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 22562df..f959cff 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -160,7 +160,7 @@
     LOG(INFO) << "ImageSpace::Init entering image_file_name=" << image_file_name;
   }
 
-  UniquePtr<File> file(OS::OpenFile(image_file_name.c_str(), false));
+  UniquePtr<File> file(OS::OpenFileForReading(image_file_name.c_str()));
   if (file.get() == NULL) {
     LOG(ERROR) << "Failed to open " << image_file_name;
     return NULL;
diff --git a/runtime/image_test.cc b/runtime/image_test.cc
index 334f7ab..dcafc19 100644
--- a/runtime/image_test.cc
+++ b/runtime/image_test.cc
@@ -65,7 +65,7 @@
     }
   }
   // Workound bug that mcld::Linker::emit closes tmp_elf by reopening as tmp_oat.
-  UniquePtr<File> tmp_oat(OS::OpenFile(tmp_elf.GetFilename().c_str(), true, false));
+  UniquePtr<File> tmp_oat(OS::OpenFileReadWrite(tmp_elf.GetFilename().c_str()));
   ASSERT_TRUE(tmp_oat.get() != NULL);
 
   ScratchFile tmp_image;
@@ -80,7 +80,7 @@
   }
 
   {
-    UniquePtr<File> file(OS::OpenFile(tmp_image.GetFilename().c_str(), false));
+    UniquePtr<File> file(OS::OpenFileForReading(tmp_image.GetFilename().c_str()));
     ASSERT_TRUE(file.get() != NULL);
     ImageHeader image_header;
     file->ReadFully(&image_header, sizeof(image_header));
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 852dd00..390a2fd 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -608,6 +608,11 @@
   return result;
 }
 
+#define CHECK_NON_NULL_ARGUMENT(fn, value) \
+  if (UNLIKELY(value == NULL)) { \
+    JniAbortF(#fn, #value " == null"); \
+  }
+
 class JNI {
  public:
   static jint GetVersion(JNIEnv*) {
@@ -620,6 +625,7 @@
   }
 
   static jclass FindClass(JNIEnv* env, const char* name) {
+    CHECK_NON_NULL_ARGUMENT(FindClass, name);
     Runtime* runtime = Runtime::Current();
     ClassLinker* class_linker = runtime->GetClassLinker();
     std::string descriptor(NormalizeJniClassDescriptor(name));
@@ -635,6 +641,7 @@
   }
 
   static jmethodID FromReflectedMethod(JNIEnv* env, jobject java_method) {
+    CHECK_NON_NULL_ARGUMENT(FromReflectedMethod, java_method);
     ScopedObjectAccess soa(env);
     jobject art_method = env->GetObjectField(java_method,
                                              WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
@@ -644,6 +651,7 @@
   }
 
   static jfieldID FromReflectedField(JNIEnv* env, jobject java_field) {
+    CHECK_NON_NULL_ARGUMENT(FromReflectedField, java_field);
     ScopedObjectAccess soa(env);
     jobject art_field = env->GetObjectField(java_field,
                                             WellKnownClasses::java_lang_reflect_Field_artField);
@@ -653,6 +661,7 @@
   }
 
   static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
+    CHECK_NON_NULL_ARGUMENT(ToReflectedMethod, mid);
     ScopedObjectAccess soa(env);
     ArtMethod* m = soa.DecodeMethod(mid);
     jobject art_method = soa.AddLocalReference<jobject>(m);
@@ -668,6 +677,7 @@
   }
 
   static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
+    CHECK_NON_NULL_ARGUMENT(ToReflectedField, fid);
     ScopedObjectAccess soa(env);
     ArtField* f = soa.DecodeField(fid);
     jobject art_field = soa.AddLocalReference<jobject>(f);
@@ -683,18 +693,22 @@
   }
 
   static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
+    CHECK_NON_NULL_ARGUMENT(GetObjectClass, java_object);
     ScopedObjectAccess soa(env);
     Object* o = soa.Decode<Object*>(java_object);
     return soa.AddLocalReference<jclass>(o->GetClass());
   }
 
   static jclass GetSuperclass(JNIEnv* env, jclass java_class) {
+    CHECK_NON_NULL_ARGUMENT(GetSuperclass, java_class);
     ScopedObjectAccess soa(env);
     Class* c = soa.Decode<Class*>(java_class);
     return soa.AddLocalReference<jclass>(c->GetSuperClass());
   }
 
   static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) {
+    CHECK_NON_NULL_ARGUMENT(IsAssignableFrom, java_class1);
+    CHECK_NON_NULL_ARGUMENT(IsAssignableFrom, java_class2);
     ScopedObjectAccess soa(env);
     Class* c1 = soa.Decode<Class*>(java_class1);
     Class* c2 = soa.Decode<Class*>(java_class2);
@@ -702,9 +716,7 @@
   }
 
   static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) {
-    if (java_class == NULL) {
-      JniAbortF("IsInstanceOf", "null class (second argument)");
-    }
+    CHECK_NON_NULL_ARGUMENT(IsInstanceOf, java_class);
     if (jobj == NULL) {
       // Note: JNI is different from regular Java instanceof in this respect
       return JNI_TRUE;
@@ -728,6 +740,7 @@
   }
 
   static jint ThrowNew(JNIEnv* env, jclass c, const char* msg) {
+    CHECK_NON_NULL_ARGUMENT(ThrowNew, c);
     return ThrowNewException(env, c, msg, NULL);
   }
 
@@ -888,6 +901,7 @@
   }
 
   static jobject AllocObject(JNIEnv* env, jclass java_class) {
+    CHECK_NON_NULL_ARGUMENT(AllocObject, java_class);
     ScopedObjectAccess soa(env);
     Class* c = soa.Decode<Class*>(java_class);
     if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
@@ -896,15 +910,19 @@
     return soa.AddLocalReference<jobject>(c->AllocObject(soa.Self()));
   }
 
-  static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
+  static jobject NewObject(JNIEnv* env, jclass java_class, jmethodID mid, ...) {
     va_list args;
     va_start(args, mid);
-    jobject result = NewObjectV(env, c, mid, args);
+    CHECK_NON_NULL_ARGUMENT(NewObject, java_class);
+    CHECK_NON_NULL_ARGUMENT(NewObject, mid);
+    jobject result = NewObjectV(env, java_class, mid, args);
     va_end(args);
     return result;
   }
 
   static jobject NewObjectV(JNIEnv* env, jclass java_class, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(NewObjectV, java_class);
+    CHECK_NON_NULL_ARGUMENT(NewObjectV, mid);
     ScopedObjectAccess soa(env);
     Class* c = soa.Decode<Class*>(java_class);
     if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
@@ -924,6 +942,8 @@
   }
 
   static jobject NewObjectA(JNIEnv* env, jclass java_class, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(NewObjectA, java_class);
+    CHECK_NON_NULL_ARGUMENT(NewObjectA, mid);
     ScopedObjectAccess soa(env);
     Class* c = soa.Decode<Class*>(java_class);
     if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
@@ -942,19 +962,28 @@
     }
   }
 
-  static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
+  static jmethodID GetMethodID(JNIEnv* env, jclass java_class, const char* name, const char* sig) {
+    CHECK_NON_NULL_ARGUMENT(GetMethodID, java_class);
+    CHECK_NON_NULL_ARGUMENT(GetMethodID, name);
+    CHECK_NON_NULL_ARGUMENT(GetMethodID, sig);
     ScopedObjectAccess soa(env);
-    return FindMethodID(soa, c, name, sig, false);
+    return FindMethodID(soa, java_class, name, sig, false);
   }
 
-  static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
+  static jmethodID GetStaticMethodID(JNIEnv* env, jclass java_class, const char* name,
+                                     const char* sig) {
+    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, java_class);
+    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, name);
+    CHECK_NON_NULL_ARGUMENT(GetStaticMethodID, sig);
     ScopedObjectAccess soa(env);
-    return FindMethodID(soa, c, name, sig, true);
+    return FindMethodID(soa, java_class, name, sig, true);
   }
 
   static jobject CallObjectMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallObjectMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallObjectMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -962,12 +991,16 @@
   }
 
   static jobject CallObjectMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallObjectMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallObjectMethodV, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
   }
 
   static jobject CallObjectMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallObjectMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallObjectMethodA, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
@@ -976,6 +1009,8 @@
   static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallBooleanMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallBooleanMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -983,30 +1018,40 @@
   }
 
   static jboolean CallBooleanMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetZ();
   }
 
   static jboolean CallBooleanMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallBooleanMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetZ();
   }
 
   static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
-    ScopedObjectAccess soa(env);
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallByteMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallByteMethod, mid);
+    ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetB();
   }
 
   static jbyte CallByteMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallByteMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallByteMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetB();
   }
 
   static jbyte CallByteMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallByteMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallByteMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetB();
   }
@@ -1014,6 +1059,8 @@
   static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallCharMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallCharMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1021,11 +1068,15 @@
   }
 
   static jchar CallCharMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallCharMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallCharMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetC();
   }
 
   static jchar CallCharMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallCharMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallCharMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetC();
   }
@@ -1033,6 +1084,8 @@
   static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallDoubleMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallDoubleMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1040,30 +1093,40 @@
   }
 
   static jdouble CallDoubleMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetD();
   }
 
   static jdouble CallDoubleMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallDoubleMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetD();
   }
 
   static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
-    ScopedObjectAccess soa(env);
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallFloatMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallFloatMethod, mid);
+    ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetF();
   }
 
   static jfloat CallFloatMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallFloatMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallFloatMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetF();
   }
 
   static jfloat CallFloatMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallFloatMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallFloatMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetF();
   }
@@ -1071,6 +1134,8 @@
   static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallIntMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallIntMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1078,11 +1143,15 @@
   }
 
   static jint CallIntMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallIntMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallIntMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetI();
   }
 
   static jint CallIntMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallIntMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallIntMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetI();
   }
@@ -1090,6 +1159,8 @@
   static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallLongMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallLongMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1097,11 +1168,15 @@
   }
 
   static jlong CallLongMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallLongMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallLongMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetJ();
   }
 
   static jlong CallLongMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallLongMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallLongMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetJ();
   }
@@ -1109,6 +1184,8 @@
   static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallShortMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallShortMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
@@ -1116,11 +1193,15 @@
   }
 
   static jshort CallShortMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallShortMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallShortMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetS();
   }
 
   static jshort CallShortMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallShortMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallShortMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetS();
   }
@@ -1128,17 +1209,23 @@
   static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallVoidMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallVoidMethod, mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap);
     va_end(ap);
   }
 
   static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallVoidMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallVoidMethodV, mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args);
   }
 
   static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallVoidMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallVoidMethodA, mid);
     ScopedObjectAccess soa(env);
     InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args);
   }
@@ -1146,6 +1233,8 @@
   static jobject CallNonvirtualObjectMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     jobject local_result = soa.AddLocalReference<jobject>(result.GetL());
@@ -1153,38 +1242,48 @@
     return local_result;
   }
 
-  static jobject CallNonvirtualObjectMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jobject CallNonvirtualObjectMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                             va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodV, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
   }
 
-  static jobject CallNonvirtualObjectMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jobject CallNonvirtualObjectMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                             jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodA, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithJValues(soa, obj, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
   }
 
-  static jboolean CallNonvirtualBooleanMethod(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, ...) {
+  static jboolean CallNonvirtualBooleanMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                              ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetZ();
   }
 
-  static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                               va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetZ();
   }
 
-  static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                               jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, obj, mid, args).GetZ();
   }
@@ -1192,41 +1291,53 @@
   static jbyte CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetB();
   }
 
-  static jbyte CallNonvirtualByteMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jbyte CallNonvirtualByteMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                         va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetB();
   }
 
-  static jbyte CallNonvirtualByteMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jbyte CallNonvirtualByteMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                         jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, obj, mid, args).GetB();
   }
 
   static jchar CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
-    ScopedObjectAccess soa(env);
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethod, mid);
+    ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetC();
   }
 
-  static jchar CallNonvirtualCharMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jchar CallNonvirtualCharMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                         va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetC();
   }
 
-  static jchar CallNonvirtualCharMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jchar CallNonvirtualCharMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                         jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, obj, mid, args).GetC();
   }
@@ -1234,20 +1345,26 @@
   static jshort CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetS();
   }
 
-  static jshort CallNonvirtualShortMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jshort CallNonvirtualShortMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                           va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetS();
   }
 
-  static jshort CallNonvirtualShortMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jshort CallNonvirtualShortMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                           jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, obj, mid, args).GetS();
   }
@@ -1255,20 +1372,26 @@
   static jint CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetI();
   }
 
-  static jint CallNonvirtualIntMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jint CallNonvirtualIntMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                       va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetI();
   }
 
-  static jint CallNonvirtualIntMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jint CallNonvirtualIntMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                       jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, obj, mid, args).GetI();
   }
@@ -1276,20 +1399,26 @@
   static jlong CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetJ();
   }
 
-  static jlong CallNonvirtualLongMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jlong CallNonvirtualLongMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                         va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetJ();
   }
 
-  static jlong CallNonvirtualLongMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jlong CallNonvirtualLongMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                         jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, obj, mid, args).GetJ();
   }
@@ -1297,20 +1426,26 @@
   static jfloat CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetF();
   }
 
-  static jfloat CallNonvirtualFloatMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jfloat CallNonvirtualFloatMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                           va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetF();
   }
 
-  static jfloat CallNonvirtualFloatMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jfloat CallNonvirtualFloatMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                           jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, obj, mid, args).GetF();
   }
@@ -1318,20 +1453,26 @@
   static jdouble CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, obj, mid, ap));
     va_end(ap);
     return result.GetD();
   }
 
-  static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, va_list args) {
+  static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                             va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, obj, mid, args).GetD();
   }
 
-  static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                             jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, obj, mid, args).GetD();
   }
@@ -1339,6 +1480,8 @@
   static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethod, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethod, mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, obj, mid, ap);
     va_end(ap);
@@ -1346,28 +1489,40 @@
 
   static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
                                         va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodV, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodV, mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, obj, mid, args);
   }
 
-  static void CallNonvirtualVoidMethodA(JNIEnv* env,
-      jobject obj, jclass, jmethodID mid, jvalue* args) {
+  static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+                                        jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodA, obj);
+    CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodA, mid);
     ScopedObjectAccess soa(env);
     InvokeWithJValues(soa, obj, mid, args);
   }
 
-  static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
+  static jfieldID GetFieldID(JNIEnv* env, jclass java_class, const char* name, const char* sig) {
+    CHECK_NON_NULL_ARGUMENT(GetFieldID, java_class);
+    CHECK_NON_NULL_ARGUMENT(GetFieldID, name);
+    CHECK_NON_NULL_ARGUMENT(GetFieldID, sig);
     ScopedObjectAccess soa(env);
-    return FindFieldID(soa, c, name, sig, false);
+    return FindFieldID(soa, java_class, name, sig, false);
   }
 
-
-  static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
+  static jfieldID GetStaticFieldID(JNIEnv* env, jclass java_class, const char* name,
+                                   const char* sig) {
+    CHECK_NON_NULL_ARGUMENT(GetStaticFieldID, java_class);
+    CHECK_NON_NULL_ARGUMENT(GetStaticFieldID, name);
+    CHECK_NON_NULL_ARGUMENT(GetFieldID, sig);
     ScopedObjectAccess soa(env);
-    return FindFieldID(soa, c, name, sig, true);
+    return FindFieldID(soa, java_class, name, sig, true);
   }
 
   static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fid) {
+    CHECK_NON_NULL_ARGUMENT(GetObjectField, obj);
+    CHECK_NON_NULL_ARGUMENT(GetObjectField, fid);
     ScopedObjectAccess soa(env);
     Object* o = soa.Decode<Object*>(obj);
     ArtField* f = soa.DecodeField(fid);
@@ -1375,12 +1530,15 @@
   }
 
   static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
+    CHECK_NON_NULL_ARGUMENT(GetStaticObjectField, fid);
     ScopedObjectAccess soa(env);
     ArtField* f = soa.DecodeField(fid);
     return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass()));
   }
 
   static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) {
+    CHECK_NON_NULL_ARGUMENT(SetObjectField, java_object);
+    CHECK_NON_NULL_ARGUMENT(SetObjectField, fid);
     ScopedObjectAccess soa(env);
     Object* o = soa.Decode<Object*>(java_object);
     Object* v = soa.Decode<Object*>(java_value);
@@ -1389,6 +1547,7 @@
   }
 
   static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
+    CHECK_NON_NULL_ARGUMENT(SetStaticObjectField, fid);
     ScopedObjectAccess soa(env);
     Object* v = soa.Decode<Object*>(java_value);
     ArtField* f = soa.DecodeField(fid);
@@ -1396,158 +1555,165 @@
   }
 
 #define GET_PRIMITIVE_FIELD(fn, instance) \
+  CHECK_NON_NULL_ARGUMENT(Get #fn Field, instance); \
+  CHECK_NON_NULL_ARGUMENT(Get #fn Field, fid); \
   ScopedObjectAccess soa(env); \
   Object* o = soa.Decode<Object*>(instance); \
   ArtField* f = soa.DecodeField(fid); \
-  return f->fn(o)
+  return f->Get ##fn (o)
 
 #define GET_STATIC_PRIMITIVE_FIELD(fn) \
+  CHECK_NON_NULL_ARGUMENT(GetStatic #fn Field, fid); \
   ScopedObjectAccess soa(env); \
   ArtField* f = soa.DecodeField(fid); \
-  return f->fn(f->GetDeclaringClass())
+  return f->Get ##fn (f->GetDeclaringClass())
 
 #define SET_PRIMITIVE_FIELD(fn, instance, value) \
+  CHECK_NON_NULL_ARGUMENT(Set #fn Field, instance); \
+  CHECK_NON_NULL_ARGUMENT(Set #fn Field, fid); \
   ScopedObjectAccess soa(env); \
   Object* o = soa.Decode<Object*>(instance); \
   ArtField* f = soa.DecodeField(fid); \
-  f->fn(o, value)
+  f->Set ##fn(o, value)
 
 #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
+  CHECK_NON_NULL_ARGUMENT(SetStatic #fn Field, fid); \
   ScopedObjectAccess soa(env); \
   ArtField* f = soa.DecodeField(fid); \
-  f->fn(f->GetDeclaringClass(), value)
+  f->Set ##fn(f->GetDeclaringClass(), value)
 
   static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
-    GET_PRIMITIVE_FIELD(GetBoolean, obj);
+    GET_PRIMITIVE_FIELD(Boolean, obj);
   }
 
   static jbyte GetByteField(JNIEnv* env, jobject obj, jfieldID fid) {
-    GET_PRIMITIVE_FIELD(GetByte, obj);
+    GET_PRIMITIVE_FIELD(Byte, obj);
   }
 
   static jchar GetCharField(JNIEnv* env, jobject obj, jfieldID fid) {
-    GET_PRIMITIVE_FIELD(GetChar, obj);
+    GET_PRIMITIVE_FIELD(Char, obj);
   }
 
   static jshort GetShortField(JNIEnv* env, jobject obj, jfieldID fid) {
-    GET_PRIMITIVE_FIELD(GetShort, obj);
+    GET_PRIMITIVE_FIELD(Short, obj);
   }
 
   static jint GetIntField(JNIEnv* env, jobject obj, jfieldID fid) {
-    GET_PRIMITIVE_FIELD(GetInt, obj);
+    GET_PRIMITIVE_FIELD(Int, obj);
   }
 
   static jlong GetLongField(JNIEnv* env, jobject obj, jfieldID fid) {
-    GET_PRIMITIVE_FIELD(GetLong, obj);
+    GET_PRIMITIVE_FIELD(Long, obj);
   }
 
   static jfloat GetFloatField(JNIEnv* env, jobject obj, jfieldID fid) {
-    GET_PRIMITIVE_FIELD(GetFloat, obj);
+    GET_PRIMITIVE_FIELD(Float, obj);
   }
 
   static jdouble GetDoubleField(JNIEnv* env, jobject obj, jfieldID fid) {
-    GET_PRIMITIVE_FIELD(GetDouble, obj);
+    GET_PRIMITIVE_FIELD(Double, obj);
   }
 
   static jboolean GetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid) {
-    GET_STATIC_PRIMITIVE_FIELD(GetBoolean);
+    GET_STATIC_PRIMITIVE_FIELD(Boolean);
   }
 
   static jbyte GetStaticByteField(JNIEnv* env, jclass, jfieldID fid) {
-    GET_STATIC_PRIMITIVE_FIELD(GetByte);
+    GET_STATIC_PRIMITIVE_FIELD(Byte);
   }
 
   static jchar GetStaticCharField(JNIEnv* env, jclass, jfieldID fid) {
-    GET_STATIC_PRIMITIVE_FIELD(GetChar);
+    GET_STATIC_PRIMITIVE_FIELD(Char);
   }
 
   static jshort GetStaticShortField(JNIEnv* env, jclass, jfieldID fid) {
-    GET_STATIC_PRIMITIVE_FIELD(GetShort);
+    GET_STATIC_PRIMITIVE_FIELD(Short);
   }
 
   static jint GetStaticIntField(JNIEnv* env, jclass, jfieldID fid) {
-    GET_STATIC_PRIMITIVE_FIELD(GetInt);
+    GET_STATIC_PRIMITIVE_FIELD(Int);
   }
 
   static jlong GetStaticLongField(JNIEnv* env, jclass, jfieldID fid) {
-    GET_STATIC_PRIMITIVE_FIELD(GetLong);
+    GET_STATIC_PRIMITIVE_FIELD(Long);
   }
 
   static jfloat GetStaticFloatField(JNIEnv* env, jclass, jfieldID fid) {
-    GET_STATIC_PRIMITIVE_FIELD(GetFloat);
+    GET_STATIC_PRIMITIVE_FIELD(Float);
   }
 
   static jdouble GetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid) {
-    GET_STATIC_PRIMITIVE_FIELD(GetDouble);
+    GET_STATIC_PRIMITIVE_FIELD(Double);
   }
 
   static void SetBooleanField(JNIEnv* env, jobject obj, jfieldID fid, jboolean v) {
-    SET_PRIMITIVE_FIELD(SetBoolean, obj, v);
+    SET_PRIMITIVE_FIELD(Boolean, obj, v);
   }
 
   static void SetByteField(JNIEnv* env, jobject obj, jfieldID fid, jbyte v) {
-    SET_PRIMITIVE_FIELD(SetByte, obj, v);
+    SET_PRIMITIVE_FIELD(Byte, obj, v);
   }
 
   static void SetCharField(JNIEnv* env, jobject obj, jfieldID fid, jchar v) {
-    SET_PRIMITIVE_FIELD(SetChar, obj, v);
+    SET_PRIMITIVE_FIELD(Char, obj, v);
   }
 
   static void SetFloatField(JNIEnv* env, jobject obj, jfieldID fid, jfloat v) {
-    SET_PRIMITIVE_FIELD(SetFloat, obj, v);
+    SET_PRIMITIVE_FIELD(Float, obj, v);
   }
 
   static void SetDoubleField(JNIEnv* env, jobject obj, jfieldID fid, jdouble v) {
-    SET_PRIMITIVE_FIELD(SetDouble, obj, v);
+    SET_PRIMITIVE_FIELD(Double, obj, v);
   }
 
   static void SetIntField(JNIEnv* env, jobject obj, jfieldID fid, jint v) {
-    SET_PRIMITIVE_FIELD(SetInt, obj, v);
+    SET_PRIMITIVE_FIELD(Int, obj, v);
   }
 
   static void SetLongField(JNIEnv* env, jobject obj, jfieldID fid, jlong v) {
-    SET_PRIMITIVE_FIELD(SetLong, obj, v);
+    SET_PRIMITIVE_FIELD(Long, obj, v);
   }
 
   static void SetShortField(JNIEnv* env, jobject obj, jfieldID fid, jshort v) {
-    SET_PRIMITIVE_FIELD(SetShort, obj, v);
+    SET_PRIMITIVE_FIELD(Short, obj, v);
   }
 
   static void SetStaticBooleanField(JNIEnv* env, jclass, jfieldID fid, jboolean v) {
-    SET_STATIC_PRIMITIVE_FIELD(SetBoolean, v);
+    SET_STATIC_PRIMITIVE_FIELD(Boolean, v);
   }
 
   static void SetStaticByteField(JNIEnv* env, jclass, jfieldID fid, jbyte v) {
-    SET_STATIC_PRIMITIVE_FIELD(SetByte, v);
+    SET_STATIC_PRIMITIVE_FIELD(Byte, v);
   }
 
   static void SetStaticCharField(JNIEnv* env, jclass, jfieldID fid, jchar v) {
-    SET_STATIC_PRIMITIVE_FIELD(SetChar, v);
+    SET_STATIC_PRIMITIVE_FIELD(Char, v);
   }
 
   static void SetStaticFloatField(JNIEnv* env, jclass, jfieldID fid, jfloat v) {
-    SET_STATIC_PRIMITIVE_FIELD(SetFloat, v);
+    SET_STATIC_PRIMITIVE_FIELD(Float, v);
   }
 
   static void SetStaticDoubleField(JNIEnv* env, jclass, jfieldID fid, jdouble v) {
-    SET_STATIC_PRIMITIVE_FIELD(SetDouble, v);
+    SET_STATIC_PRIMITIVE_FIELD(Double, v);
   }
 
   static void SetStaticIntField(JNIEnv* env, jclass, jfieldID fid, jint v) {
-    SET_STATIC_PRIMITIVE_FIELD(SetInt, v);
+    SET_STATIC_PRIMITIVE_FIELD(Int, v);
   }
 
   static void SetStaticLongField(JNIEnv* env, jclass, jfieldID fid, jlong v) {
-    SET_STATIC_PRIMITIVE_FIELD(SetLong, v);
+    SET_STATIC_PRIMITIVE_FIELD(Long, v);
   }
 
   static void SetStaticShortField(JNIEnv* env, jclass, jfieldID fid, jshort v) {
-    SET_STATIC_PRIMITIVE_FIELD(SetShort, v);
+    SET_STATIC_PRIMITIVE_FIELD(Short, v);
   }
 
   static jobject CallStaticObjectMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     jobject local_result = soa.AddLocalReference<jobject>(result.GetL());
@@ -1556,12 +1722,14 @@
   }
 
   static jobject CallStaticObjectMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethodV, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
   }
 
   static jobject CallStaticObjectMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticObjectMethodA, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithJValues(soa, NULL, mid, args));
     return soa.AddLocalReference<jobject>(result.GetL());
@@ -1570,6 +1738,7 @@
   static jboolean CallStaticBooleanMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     va_end(ap);
@@ -1577,11 +1746,13 @@
   }
 
   static jboolean CallStaticBooleanMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, NULL, mid, args).GetZ();
   }
 
   static jboolean CallStaticBooleanMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticBooleanMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, NULL, mid, args).GetZ();
   }
@@ -1589,6 +1760,7 @@
   static jbyte CallStaticByteMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     va_end(ap);
@@ -1596,11 +1768,13 @@
   }
 
   static jbyte CallStaticByteMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, NULL, mid, args).GetB();
   }
 
   static jbyte CallStaticByteMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticByteMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, NULL, mid, args).GetB();
   }
@@ -1608,6 +1782,7 @@
   static jchar CallStaticCharMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     va_end(ap);
@@ -1615,11 +1790,13 @@
   }
 
   static jchar CallStaticCharMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, NULL, mid, args).GetC();
   }
 
   static jchar CallStaticCharMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticCharMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, NULL, mid, args).GetC();
   }
@@ -1627,6 +1804,7 @@
   static jshort CallStaticShortMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     va_end(ap);
@@ -1634,11 +1812,13 @@
   }
 
   static jshort CallStaticShortMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, NULL, mid, args).GetS();
   }
 
   static jshort CallStaticShortMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticShortMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, NULL, mid, args).GetS();
   }
@@ -1646,6 +1826,7 @@
   static jint CallStaticIntMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     va_end(ap);
@@ -1653,11 +1834,13 @@
   }
 
   static jint CallStaticIntMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, NULL, mid, args).GetI();
   }
 
   static jint CallStaticIntMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticIntMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, NULL, mid, args).GetI();
   }
@@ -1665,6 +1848,7 @@
   static jlong CallStaticLongMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     va_end(ap);
@@ -1672,11 +1856,13 @@
   }
 
   static jlong CallStaticLongMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, NULL, mid, args).GetJ();
   }
 
   static jlong CallStaticLongMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticLongMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, NULL, mid, args).GetJ();
   }
@@ -1684,6 +1870,7 @@
   static jfloat CallStaticFloatMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     va_end(ap);
@@ -1691,11 +1878,13 @@
   }
 
   static jfloat CallStaticFloatMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, NULL, mid, args).GetF();
   }
 
   static jfloat CallStaticFloatMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticFloatMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, NULL, mid, args).GetF();
   }
@@ -1703,6 +1892,7 @@
   static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethod, mid);
     ScopedObjectAccess soa(env);
     JValue result(InvokeWithVarArgs(soa, NULL, mid, ap));
     va_end(ap);
@@ -1710,11 +1900,13 @@
   }
 
   static jdouble CallStaticDoubleMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethodV, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithVarArgs(soa, NULL, mid, args).GetD();
   }
 
   static jdouble CallStaticDoubleMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticDoubleMethodA, mid);
     ScopedObjectAccess soa(env);
     return InvokeWithJValues(soa, NULL, mid, args).GetD();
   }
@@ -1722,22 +1914,28 @@
   static void CallStaticVoidMethod(JNIEnv* env, jclass, jmethodID mid, ...) {
     va_list ap;
     va_start(ap, mid);
+    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethod, mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, NULL, mid, ap);
     va_end(ap);
   }
 
   static void CallStaticVoidMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethodV, mid);
     ScopedObjectAccess soa(env);
     InvokeWithVarArgs(soa, NULL, mid, args);
   }
 
   static void CallStaticVoidMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) {
+    CHECK_NON_NULL_ARGUMENT(CallStaticVoidMethodA, mid);
     ScopedObjectAccess soa(env);
     InvokeWithJValues(soa, NULL, mid, args);
   }
 
   static jstring NewString(JNIEnv* env, const jchar* chars, jsize char_count) {
+    if (UNLIKELY(chars == NULL && char_count > 0)) { \
+      JniAbortF("NewString", "char == null && char_count > 0"); \
+    }
     ScopedObjectAccess soa(env);
     String* result = String::AllocFromUtf16(soa.Self(), char_count, chars);
     return soa.AddLocalReference<jstring>(result);
@@ -1753,38 +1951,47 @@
   }
 
   static jsize GetStringLength(JNIEnv* env, jstring java_string) {
+    CHECK_NON_NULL_ARGUMENT(GetStringLength, java_string);
     ScopedObjectAccess soa(env);
     return soa.Decode<String*>(java_string)->GetLength();
   }
 
   static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) {
+    CHECK_NON_NULL_ARGUMENT(GetStringLength, java_string);
     ScopedObjectAccess soa(env);
     return soa.Decode<String*>(java_string)->GetUtfLength();
   }
 
-  static void GetStringRegion(JNIEnv* env, jstring java_string, jsize start, jsize length, jchar* buf) {
+  static void GetStringRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
+                              jchar* buf) {
+    CHECK_NON_NULL_ARGUMENT(GetStringRegion, java_string);
     ScopedObjectAccess soa(env);
     String* s = soa.Decode<String*>(java_string);
     if (start < 0 || length < 0 || start + length > s->GetLength()) {
       ThrowSIOOBE(soa, start, length, s->GetLength());
     } else {
+      CHECK_NON_NULL_ARGUMENT(GetStringRegion, buf);
       const jchar* chars = s->GetCharArray()->GetData() + s->GetOffset();
       memcpy(buf, chars + start, length * sizeof(jchar));
     }
   }
 
-  static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length, char* buf) {
+  static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length,
+                                 char* buf) {
+    CHECK_NON_NULL_ARGUMENT(GetStringUTFRegion, java_string);
     ScopedObjectAccess soa(env);
     String* s = soa.Decode<String*>(java_string);
     if (start < 0 || length < 0 || start + length > s->GetLength()) {
       ThrowSIOOBE(soa, start, length, s->GetLength());
     } else {
+      CHECK_NON_NULL_ARGUMENT(GetStringUTFRegion, buf);
       const jchar* chars = s->GetCharArray()->GetData() + s->GetOffset();
       ConvertUtf16ToModifiedUtf8(buf, chars + start, length);
     }
   }
 
   static const jchar* GetStringChars(JNIEnv* env, jstring java_string, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetStringUTFRegion, java_string);
     ScopedObjectAccess soa(env);
     String* s = soa.Decode<String*>(java_string);
     const CharArray* chars = s->GetCharArray();
@@ -1796,6 +2003,7 @@
   }
 
   static void ReleaseStringChars(JNIEnv* env, jstring java_string, const jchar*) {
+    CHECK_NON_NULL_ARGUMENT(GetStringUTFRegion, java_string);
     ScopedObjectAccess soa(env);
     UnpinPrimitiveArray(soa, soa.Decode<String*>(java_string)->GetCharArray());
   }
@@ -1805,7 +2013,6 @@
   }
 
   static void ReleaseStringCritical(JNIEnv* env, jstring java_string, const jchar* chars) {
-    ScopedObjectAccess soa(env);
     return ReleaseStringChars(env, java_string, chars);
   }
 
@@ -1832,6 +2039,7 @@
   }
 
   static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
+    CHECK_NON_NULL_ARGUMENT(GetArrayLength, java_array);
     ScopedObjectAccess soa(env);
     Object* obj = soa.Decode<Object*>(java_array);
     if (UNLIKELY(!obj->IsArrayInstance())) {
@@ -1842,13 +2050,15 @@
   }
 
   static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index) {
+    CHECK_NON_NULL_ARGUMENT(GetObjectArrayElement, java_array);
     ScopedObjectAccess soa(env);
     ObjectArray<Object>* array = soa.Decode<ObjectArray<Object>*>(java_array);
     return soa.AddLocalReference<jobject>(array->Get(index));
   }
 
-  static void SetObjectArrayElement(JNIEnv* env,
-      jobjectArray java_array, jsize index, jobject java_value) {
+  static void SetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index,
+                                    jobject java_value) {
+    CHECK_NON_NULL_ARGUMENT(SetObjectArrayElement, java_array);
     ScopedObjectAccess soa(env);
     ObjectArray<Object>* array = soa.Decode<ObjectArray<Object>*>(java_array);
     Object* value = soa.Decode<Object*>(java_value);
@@ -1926,6 +2136,7 @@
   }
 
   static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray java_array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetPrimitiveArrayCritical, java_array);
     ScopedObjectAccess soa(env);
     Array* array = soa.Decode<Array*>(java_array);
     PinPrimitiveArray(soa, array);
@@ -1936,45 +2147,54 @@
   }
 
   static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void*, jint mode) {
+    CHECK_NON_NULL_ARGUMENT(ReleasePrimitiveArrayCritical, array);
     ReleasePrimitiveArray(env, array, mode);
   }
 
   static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetBooleanArrayElements, array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jbooleanArray, jboolean*, BooleanArray>(soa, array, is_copy);
   }
 
   static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetByteArrayElements, array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jbyteArray, jbyte*, ByteArray>(soa, array, is_copy);
   }
 
   static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetCharArrayElements, array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jcharArray, jchar*, CharArray>(soa, array, is_copy);
   }
 
   static jdouble* GetDoubleArrayElements(JNIEnv* env, jdoubleArray array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetDoubleArrayElements, array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jdoubleArray, jdouble*, DoubleArray>(soa, array, is_copy);
   }
 
   static jfloat* GetFloatArrayElements(JNIEnv* env, jfloatArray array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetFloatArrayElements, array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jfloatArray, jfloat*, FloatArray>(soa, array, is_copy);
   }
 
   static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetIntArrayElements, array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jintArray, jint*, IntArray>(soa, array, is_copy);
   }
 
   static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetLongArrayElements, array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jlongArray, jlong*, LongArray>(soa, array, is_copy);
   }
 
   static jshort* GetShortArrayElements(JNIEnv* env, jshortArray array, jboolean* is_copy) {
+    CHECK_NON_NULL_ARGUMENT(GetShortArrayElements, array);
     ScopedObjectAccess soa(env);
     return GetPrimitiveArray<jshortArray, jshort*, ShortArray>(soa, array, is_copy);
   }
@@ -2011,95 +2231,123 @@
     ReleasePrimitiveArray(env, array, mode);
   }
 
-  static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, jboolean* buf) {
+  static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length,
+                                    jboolean* buf) {
     ScopedObjectAccess soa(env);
     GetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(soa, array, start, length, buf);
   }
 
-  static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, jbyte* buf) {
+  static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length,
+                                 jbyte* buf) {
     ScopedObjectAccess soa(env);
     GetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(soa, array, start, length, buf);
   }
 
-  static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, jchar* buf) {
+  static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length,
+                                 jchar* buf) {
     ScopedObjectAccess soa(env);
     GetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(soa, array, start, length, buf);
   }
 
-  static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, jdouble* buf) {
+  static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length,
+                                   jdouble* buf) {
     ScopedObjectAccess soa(env);
     GetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(soa, array, start, length, buf);
   }
 
-  static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, jfloat* buf) {
+  static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length,
+                                  jfloat* buf) {
     ScopedObjectAccess soa(env);
     GetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(soa, array, start, length, buf);
   }
 
-  static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, jint* buf) {
+  static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length,
+                                jint* buf) {
     ScopedObjectAccess soa(env);
     GetPrimitiveArrayRegion<jintArray, jint, IntArray>(soa, array, start, length, buf);
   }
 
-  static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, jlong* buf) {
+  static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length,
+                                 jlong* buf) {
     ScopedObjectAccess soa(env);
     GetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(soa, array, start, length, buf);
   }
 
-  static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, jshort* buf) {
+  static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length,
+                                  jshort* buf) {
     ScopedObjectAccess soa(env);
     GetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(soa, array, start, length, buf);
   }
 
-  static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, const jboolean* buf) {
+  static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length,
+                                    const jboolean* buf) {
     ScopedObjectAccess soa(env);
     SetPrimitiveArrayRegion<jbooleanArray, jboolean, BooleanArray>(soa, array, start, length, buf);
   }
 
-  static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, const jbyte* buf) {
+  static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length,
+                                 const jbyte* buf) {
     ScopedObjectAccess soa(env);
     SetPrimitiveArrayRegion<jbyteArray, jbyte, ByteArray>(soa, array, start, length, buf);
   }
 
-  static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, const jchar* buf) {
+  static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length,
+                                 const jchar* buf) {
     ScopedObjectAccess soa(env);
     SetPrimitiveArrayRegion<jcharArray, jchar, CharArray>(soa, array, start, length, buf);
   }
 
-  static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, const jdouble* buf) {
+  static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length,
+                                   const jdouble* buf) {
     ScopedObjectAccess soa(env);
     SetPrimitiveArrayRegion<jdoubleArray, jdouble, DoubleArray>(soa, array, start, length, buf);
   }
 
-  static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, const jfloat* buf) {
+  static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length,
+                                  const jfloat* buf) {
     ScopedObjectAccess soa(env);
     SetPrimitiveArrayRegion<jfloatArray, jfloat, FloatArray>(soa, array, start, length, buf);
   }
 
-  static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, const jint* buf) {
+  static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length,
+                                const jint* buf) {
     ScopedObjectAccess soa(env);
     SetPrimitiveArrayRegion<jintArray, jint, IntArray>(soa, array, start, length, buf);
   }
 
-  static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, const jlong* buf) {
+  static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length,
+                                 const jlong* buf) {
     ScopedObjectAccess soa(env);
     SetPrimitiveArrayRegion<jlongArray, jlong, LongArray>(soa, array, start, length, buf);
   }
 
-  static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, const jshort* buf) {
+  static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length,
+                                  const jshort* buf) {
     ScopedObjectAccess soa(env);
     SetPrimitiveArrayRegion<jshortArray, jshort, ShortArray>(soa, array, start, length, buf);
   }
 
-  static jint RegisterNatives(JNIEnv* env, jclass java_class, const JNINativeMethod* methods, jint method_count) {
+  static jint RegisterNatives(JNIEnv* env, jclass java_class, const JNINativeMethod* methods,
+                              jint method_count) {
     return RegisterNativeMethods(env, java_class, methods, method_count, true);
   }
 
-  static jint RegisterNativeMethods(JNIEnv* env, jclass java_class, const JNINativeMethod* methods, size_t method_count, bool return_errors) {
+  static jint RegisterNativeMethods(JNIEnv* env, jclass java_class, const JNINativeMethod* methods,
+                                    jint method_count, bool return_errors) {
+    if (UNLIKELY(method_count < 0)) {
+      JniAbortF("RegisterNatives", "method_cound == %d", method_count);
+      return JNI_ERR;  // Not reached.
+    }
+    CHECK_NON_NULL_ARGUMENT(RegisterNatives, java_class);
     ScopedObjectAccess soa(env);
     Class* c = soa.Decode<Class*>(java_class);
-
-    for (size_t i = 0; i < method_count; ++i) {
+    if (UNLIKELY(method_count == 0)) {
+      LOG(WARNING) << "JNI RegisterNativeMethods: attempt to register 0 native methods for "
+          << PrettyDescriptor(c);
+      return JNI_OK;
+    }
+    CHECK_NON_NULL_ARGUMENT(RegisterNatives, methods);
+    for (jint i = 0; i < method_count; ++i) {
       const char* name = methods[i].name;
       const char* sig = methods[i].signature;
 
@@ -2114,13 +2362,13 @@
       }
       if (m == NULL) {
         LOG(return_errors ? ERROR : FATAL) << "Failed to register native method "
-                                           << PrettyDescriptor(c) << "." << name << sig;
+            << PrettyDescriptor(c) << "." << name << sig;
         ThrowNoSuchMethodError(soa, c, name, sig, "static or non-static");
         return JNI_ERR;
       } else if (!m->IsNative()) {
         LOG(return_errors ? ERROR : FATAL) << "Failed to register non-native method "
-                                           << PrettyDescriptor(c) << "." << name << sig
-                                           << " as native";
+            << PrettyDescriptor(c) << "." << name << sig
+            << " as native";
         ThrowNoSuchMethodError(soa, c, name, sig, "native");
         return JNI_ERR;
       }
@@ -2133,6 +2381,7 @@
   }
 
   static jint UnregisterNatives(JNIEnv* env, jclass java_class) {
+    CHECK_NON_NULL_ARGUMENT(UnregisterNatives, java_class);
     ScopedObjectAccess soa(env);
     Class* c = soa.Decode<Class*>(java_class);
 
@@ -2156,6 +2405,7 @@
 
   static jint MonitorEnter(JNIEnv* env, jobject java_object)
       EXCLUSIVE_LOCK_FUNCTION(monitor_lock_) {
+    CHECK_NON_NULL_ARGUMENT(MonitorEnter, java_object);
     ScopedObjectAccess soa(env);
     Object* o = soa.Decode<Object*>(java_object);
     o->MonitorEnter(soa.Self());
@@ -2168,6 +2418,7 @@
 
   static jint MonitorExit(JNIEnv* env, jobject java_object)
       UNLOCK_FUNCTION(monitor_lock_) {
+    CHECK_NON_NULL_ARGUMENT(MonitorExit, java_object);
     ScopedObjectAccess soa(env);
     Object* o = soa.Decode<Object*>(java_object);
     o->MonitorExit(soa.Self());
@@ -2179,6 +2430,7 @@
   }
 
   static jint GetJavaVM(JNIEnv* env, JavaVM** vm) {
+    CHECK_NON_NULL_ARGUMENT(GetJavaVM, vm);
     Runtime* runtime = Runtime::Current();
     if (runtime != NULL) {
       *vm = runtime->GetJavaVM();
@@ -2217,9 +2469,7 @@
   }
 
   static jobjectRefType GetObjectRefType(JNIEnv* env, jobject java_object) {
-    if (java_object == NULL) {
-      JniAbortF("GetObjectRefType", "null object");
-    }
+    CHECK_NON_NULL_ARGUMENT(GetObjectRefType, java_object);
 
     // Do we definitely know what kind of reference this is?
     IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
@@ -2313,10 +2563,12 @@
   static void GetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
                                       jsize start, jsize length, JavaT* buf)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    CHECK_NON_NULL_ARGUMENT(GetPrimitiveArrayRegion, java_array);
     ArrayT* array = soa.Decode<ArrayT*>(java_array);
     if (start < 0 || length < 0 || start + length > array->GetLength()) {
       ThrowAIOOBE(soa, array, start, length, "src");
     } else {
+      CHECK_NON_NULL_ARGUMENT(GetPrimitiveArrayRegion, buf);
       JavaT* data = array->GetData();
       memcpy(buf, data + start, length * sizeof(JavaT));
     }
@@ -2326,10 +2578,12 @@
   static void SetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array,
                                       jsize start, jsize length, const JavaT* buf)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    CHECK_NON_NULL_ARGUMENT(SetPrimitiveArrayRegion, java_array);
     ArrayT* array = soa.Decode<ArrayT*>(java_array);
     if (start < 0 || length < 0 || start + length > array->GetLength()) {
       ThrowAIOOBE(soa, array, start, length, "dst");
     } else {
+      CHECK_NON_NULL_ARGUMENT(SetPrimitiveArrayRegion, buf);
       JavaT* data = array->GetData();
       memcpy(data + start, buf, length * sizeof(JavaT));
     }
@@ -2971,7 +3225,7 @@
 }
 
 void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods,
-                           size_t method_count) {
+                           jint method_count) {
   ScopedLocalRef<jclass> c(env, env->FindClass(jni_class_name));
   if (c.get() == NULL) {
     LOG(FATAL) << "Couldn't find class: " << jni_class_name;
diff --git a/runtime/jni_internal.h b/runtime/jni_internal.h
index e3ffc84..f7caa0f 100644
--- a/runtime/jni_internal.h
+++ b/runtime/jni_internal.h
@@ -51,7 +51,7 @@
 void JniAbortF(const char* jni_function_name, const char* fmt, ...)
     __attribute__((__format__(__printf__, 2, 3)));
 void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods,
-                           size_t method_count);
+                           jint method_count);
 
 JValue InvokeWithJValues(const ScopedObjectAccess&, jobject obj, jmethodID mid, jvalue* args)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index dc3573d..061dfb8 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -84,7 +84,7 @@
   void operator=(const NullableScopedUtfChars&);
 };
 
-static jint DexFile_openDexFile(JNIEnv* env, jclass, jstring javaSourceName, jstring javaOutputName, jint) {
+static jint DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceName, jstring javaOutputName, jint) {
   ScopedUtfChars sourceName(env, javaSourceName);
   if (sourceName.c_str() == NULL) {
     return 0;
@@ -141,21 +141,25 @@
   ScopedObjectAccess soa(env);
   const DexFile* dex_file = toDexFile(cookie);
   if (dex_file == NULL) {
+    VLOG(class_linker) << "Failed to find dex_file";
     return NULL;
   }
   ScopedUtfChars class_name(env, javaName);
   if (class_name.c_str() == NULL) {
+    VLOG(class_linker) << "Failed to find class_name";
     return NULL;
   }
   const std::string descriptor(DotToDescriptor(class_name.c_str()));
   const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
   if (dex_class_def == NULL) {
+    VLOG(class_linker) << "Failed to find dex_class_def";
     return NULL;
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   class_linker->RegisterDexFile(*dex_file);
   mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(javaLoader);
   mirror::Class* result = class_linker->DefineClass(descriptor, class_loader, *dex_file, *dex_class_def);
+  VLOG(class_linker) << "DexFile_defineClassNative returning " << result;
   return soa.AddLocalReference<jclass>(result);
 }
 
@@ -300,7 +304,7 @@
   NATIVE_METHOD(DexFile, defineClassNative, "(Ljava/lang/String;Ljava/lang/ClassLoader;I)Ljava/lang/Class;"),
   NATIVE_METHOD(DexFile, getClassNameList, "(I)[Ljava/lang/String;"),
   NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"),
-  NATIVE_METHOD(DexFile, openDexFile, "(Ljava/lang/String;Ljava/lang/String;I)I"),
+  NATIVE_METHOD(DexFile, openDexFileNative, "(Ljava/lang/String;Ljava/lang/String;I)I"),
 };
 
 void register_dalvik_system_DexFile(JNIEnv* env) {
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 1f34317..afa823d 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -74,7 +74,7 @@
   //
   // On host, dlopen is expected to fail when cross compiling, so fall back to OpenElfFile.
   // This won't work for portable runtime execution because it doesn't process relocations.
-  UniquePtr<File> file(OS::OpenFile(filename.c_str(), false, false));
+  UniquePtr<File> file(OS::OpenFileForReading(filename.c_str()));
   if (file.get() == NULL) {
     return NULL;
   }
@@ -125,11 +125,13 @@
 bool OatFile::Dlopen(const std::string& elf_filename, byte* requested_base) {
   char* absolute_path = realpath(elf_filename.c_str(), NULL);
   if (absolute_path == NULL) {
+    VLOG(class_linker) << "Failed to find absolute path for " << elf_filename;
     return false;
   }
   dlopen_handle_ = dlopen(absolute_path, RTLD_NOW);
   free(absolute_path);
   if (dlopen_handle_ == NULL) {
+    VLOG(class_linker) << "Failed to dlopen " << elf_filename << ": " << dlerror();
     return false;
   }
   begin_ = reinterpret_cast<byte*>(dlsym(dlopen_handle_, "oatdata"));
@@ -319,7 +321,14 @@
   Table::const_iterator it = oat_dex_files_.find(dex_file_location);
   if (it == oat_dex_files_.end()) {
     if (warn_if_not_found) {
-      LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location;
+      LOG(WARNING) << "Failed to find OatDexFile for DexFile " << dex_file_location
+                   << " in OatFile " << GetLocation();
+      if (kIsDebugBuild) {
+        for (Table::const_iterator it = oat_dex_files_.begin(); it != oat_dex_files_.end(); ++it) {
+          LOG(WARNING) << "OatFile " << GetLocation()
+                       << " contains OatDexFile " << it->second->GetDexFileLocation();
+        }
+      }
     }
     return NULL;
   }
@@ -360,11 +369,11 @@
   uint32_t oat_class_offset = oat_class_offsets_pointer_[class_def_index];
 
   const byte* oat_class_pointer = oat_file_->Begin() + oat_class_offset;
-  CHECK_LT(oat_class_pointer, oat_file_->End());
+  CHECK_LT(oat_class_pointer, oat_file_->End()) << oat_file_->GetLocation();
   mirror::Class::Status status = *reinterpret_cast<const mirror::Class::Status*>(oat_class_pointer);
 
   const byte* methods_pointer = oat_class_pointer + sizeof(status);
-  CHECK_LT(methods_pointer, oat_file_->End());
+  CHECK_LT(methods_pointer, oat_file_->End()) << oat_file_->GetLocation();
 
   return new OatClass(oat_file_,
                       status,
diff --git a/runtime/os.h b/runtime/os.h
index 6767566..6248d5f 100644
--- a/runtime/os.h
+++ b/runtime/os.h
@@ -29,8 +29,17 @@
 
 class OS {
  public:
-  // Open a file. The returned pointer must be deleted by the caller.
-  static File* OpenFile(const char* name, bool writable, bool create = true);
+  // Open an existing file with read only access.
+  static File* OpenFileForReading(const char* name);
+
+  // Open an existing file with read/write access.
+  static File* OpenFileReadWrite(const char* name);
+
+  // Create an empty file with read/write access.
+  static File* CreateEmptyFile(const char* name);
+
+  // Open a file with the specified open(2) flags.
+  static File* OpenFileWithFlags(const char* name, int flags);
 
   // Check if a file exists.
   static bool FileExists(const char* name);
diff --git a/runtime/os_linux.cc b/runtime/os_linux.cc
index d3a1ccb..7ce17e0 100644
--- a/runtime/os_linux.cc
+++ b/runtime/os_linux.cc
@@ -27,17 +27,20 @@
 
 namespace art {
 
-File* OS::OpenFile(const char* name, bool writable, bool create) {
+File* OS::OpenFileForReading(const char* name) {
+  return OpenFileWithFlags(name, O_RDONLY);
+}
+
+File* OS::OpenFileReadWrite(const char* name) {
+  return OpenFileWithFlags(name, O_RDWR);
+}
+
+File* OS::CreateEmptyFile(const char* name) {
+  return OpenFileWithFlags(name, O_RDWR | O_CREAT | O_TRUNC);
+}
+
+File* OS::OpenFileWithFlags(const char* name, int flags) {
   CHECK(name != NULL);
-  int flags = 0;
-  if (writable) {
-    flags |= O_RDWR;
-    if (create) {
-      flags |= (O_CREAT | O_TRUNC);
-    }
-  } else {
-    flags |= O_RDONLY;
-  }
   UniquePtr<File> file(new File);
   if (!file->Open(name, flags, 0666)) {
     return NULL;
diff --git a/runtime/output_stream_test.cc b/runtime/output_stream_test.cc
index c9e0ede..8da2ac9 100644
--- a/runtime/output_stream_test.cc
+++ b/runtime/output_stream_test.cc
@@ -62,7 +62,7 @@
   FileOutputStream output_stream(tmp.GetFile());
   SetOutputStream(output_stream);
   GenerateTestOutput();
-  UniquePtr<File> in(OS::OpenFile(tmp.GetFilename().c_str(), false));
+  UniquePtr<File> in(OS::OpenFileForReading(tmp.GetFilename().c_str()));
   EXPECT_TRUE(in.get() != NULL);
   std::vector<uint8_t> actual(in->GetLength());
   bool readSuccess = in->ReadFully(&actual[0], actual.size());
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index aaae300..c4a9503 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -166,7 +166,7 @@
         ThrowLocation throw_location;
         mirror::Throwable* exception = self->GetException(&throw_location);
         os << "Pending exception " << PrettyTypeOf(exception)
-            << " thrown by '" << throw_location.Dump() << "\n"
+            << " thrown by '" << throw_location.Dump() << "'\n"
             << exception->Dump();
       }
     }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 7e3afb5..48e595f 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2218,11 +2218,13 @@
 
 // Set the stack end to that to be used during a stack overflow
 void Thread::SetStackEndForStackOverflow() {
-  // During stack overflow we allow use of the full stack
+  // During stack overflow we allow use of the full stack.
   if (stack_end_ == stack_begin_) {
-    DumpStack(std::cerr);
-    LOG(FATAL) << "Need to increase kStackOverflowReservedBytes (currently "
-               << kStackOverflowReservedBytes << ")";
+    // However, we seem to have already extended to use the full stack.
+    LOG(ERROR) << "Need to increase kStackOverflowReservedBytes (currently "
+               << kStackOverflowReservedBytes << ")?";
+    DumpStack(LOG(ERROR));
+    LOG(FATAL) << "Recursive stack overflow.";
   }
 
   stack_end_ = stack_begin_;
diff --git a/runtime/throw_location.cc b/runtime/throw_location.cc
index 6d1ca1b..e428511 100644
--- a/runtime/throw_location.cc
+++ b/runtime/throw_location.cc
@@ -25,8 +25,12 @@
 namespace art {
 
 std::string ThrowLocation::Dump() const {
-  return StringPrintf("%s:%d", PrettyMethod(method_).c_str(),
-                      MethodHelper(method_).GetLineNumFromDexPC(dex_pc_));
+  if (method_ != NULL) {
+    return StringPrintf("%s:%d", PrettyMethod(method_).c_str(),
+                        MethodHelper(method_).GetLineNumFromDexPC(dex_pc_));
+  } else {
+    return "unknown throw location";
+  }
 }
 
 void ThrowLocation::VisitRoots(RootVisitor* visitor, void* arg) {
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 29765c9..13e2bf6 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -318,7 +318,7 @@
   UniquePtr<File> trace_file;
   if (!direct_to_ddms) {
     if (trace_fd < 0) {
-      trace_file.reset(OS::OpenFile(trace_filename, true));
+      trace_file.reset(OS::CreateEmptyFile(trace_filename));
     } else {
       trace_file.reset(new File(trace_fd, "tracefile"));
       trace_file->DisableAutoClose();
diff --git a/runtime/utils.cc b/runtime/utils.cc
index 87cd21c..6856bb7 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1229,6 +1229,7 @@
 
 bool IsValidOatFilename(const std::string& filename) {
   return (EndsWith(filename, ".odex") ||
+          EndsWith(filename, ".dex") ||
           EndsWith(filename, ".oat") ||
           EndsWith(filename, DexFile::kClassesDex));
 }
diff --git a/test/Android.mk b/test/Android.mk
index 87e15a8..596c411 100644
--- a/test/Android.mk
+++ b/test/Android.mk
@@ -111,7 +111,7 @@
 	$(hide) rm /tmp/test-art-target-oat-$(1)
 
 $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).odex: $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).jar $(HOST_CORE_IMG_OUT) | $(DEX2OAT)
-	$(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --boot-image=$(HOST_CORE_IMG_OUT) --dex-file=$$< --oat-file=$$@ --instruction-set=$(HOST_ARCH) --host --host-prefix="" --android-root=$(HOST_OUT)
+	$(DEX2OAT) --runtime-arg -Xms16m --runtime-arg -Xmx16m --boot-image=$(HOST_CORE_IMG_OUT) --dex-file=$(PWD)/$$< --oat-file=$(PWD)/$$@ --instruction-set=$(HOST_ARCH) --host --host-prefix="" --android-root=$(HOST_OUT)
 
 .PHONY: test-art-host-oat-default-$(1)
 test-art-host-oat-default-$(1): $(HOST_OUT_JAVA_LIBRARIES)/oat-test-dex-$(1).odex test-art-host-dependencies