Merge mnc changes into mnc-dr
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index 5ef744c..13825a7 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -19,6 +19,7 @@
 #include "art_method-inl.h"
 #include "arch/instruction_set.h"
 #include "arch/instruction_set_features.h"
+#include "base/stringpiece.h"
 #include "base/time_utils.h"
 #include "base/timing_logger.h"
 #include "compiler_callbacks.h"
@@ -86,7 +87,37 @@
       nullptr,
       false));
   const InstructionSet instruction_set = kRuntimeISA;
-  instruction_set_features_.reset(InstructionSetFeatures::FromCppDefines());
+  for (const StringPiece option : Runtime::Current()->GetCompilerOptions()) {
+    VLOG(compiler) << "JIT compiler option " << option;
+    std::string error_msg;
+    if (option.starts_with("--instruction-set-variant=")) {
+      StringPiece str = option.substr(strlen("--instruction-set-variant=")).data();
+      VLOG(compiler) << "JIT instruction set variant " << str;
+      instruction_set_features_.reset(InstructionSetFeatures::FromVariant(
+          instruction_set, str.as_string(), &error_msg));
+      if (instruction_set_features_ == nullptr) {
+        LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
+      }
+    } else if (option.starts_with("--instruction-set-features=")) {
+      StringPiece str = option.substr(strlen("--instruction-set-features=")).data();
+      VLOG(compiler) << "JIT instruction set features " << str;
+      if (instruction_set_features_.get() == nullptr) {
+        instruction_set_features_.reset(InstructionSetFeatures::FromVariant(
+            instruction_set, "default", &error_msg));
+        if (instruction_set_features_ == nullptr) {
+          LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
+        }
+      }
+      instruction_set_features_.reset(
+          instruction_set_features_->AddFeaturesFromString(str.as_string(), &error_msg));
+      if (instruction_set_features_ == nullptr) {
+        LOG(WARNING) << "Error parsing " << option << " message=" << error_msg;
+      }
+    }
+  }
+  if (instruction_set_features_ == nullptr) {
+    instruction_set_features_.reset(InstructionSetFeatures::FromCppDefines());
+  }
   cumulative_logger_.reset(new CumulativeLogger("jit times"));
   verification_results_.reset(new VerificationResults(compiler_options_.get()));
   method_inliner_map_.reset(new DexFileToMethodInlinerMap);
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 40ec46c..f8e4d10 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -316,7 +316,9 @@
 void ReferenceTypePropagation::ProcessWorklist() {
   while (!worklist_.IsEmpty()) {
     HInstruction* instruction = worklist_.Pop();
-    if (UpdateNullability(instruction) || UpdateReferenceTypeInfo(instruction)) {
+    bool updated_nullability = UpdateNullability(instruction);
+    bool updated_reference_type = UpdateReferenceTypeInfo(instruction);
+    if (updated_nullability || updated_reference_type) {
       AddDependentInstructionsToWorklist(instruction);
     }
   }
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index e913c20..9d7e68a 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -433,8 +433,10 @@
   // Debug builds are slower so they have larger timeouts.
   static constexpr int64_t kSlowdownFactor = kIsDebugBuild ? 5U : 1U;
 
-  // 10 minutes scaled by kSlowdownFactor.
-  static constexpr int64_t kWatchDogTimeoutSeconds = kSlowdownFactor * 10 * 60;
+  // 9.5 minutes scaled by kSlowdownFactor. This is slightly smaller than the Package Manager
+  // watchdog (PackageManagerService.WATCHDOG_TIMEOUT, 10 minutes), so that dex2oat will abort
+  // itself before that watchdog would take down the system server.
+  static constexpr int64_t kWatchDogTimeoutSeconds = kSlowdownFactor * (9 * 60 + 30);
 
   bool is_watch_dog_enabled_;
   bool shutting_down_;
@@ -502,6 +504,7 @@
       compiler_kind_(kUseOptimizingCompiler ? Compiler::kOptimizing : Compiler::kQuick),
       instruction_set_(kRuntimeISA),
       // Take the default set of instruction features from the build.
+      verification_results_(nullptr),
       method_inliner_map_(),
       runtime_(nullptr),
       thread_count_(sysconf(_SC_NPROCESSORS_CONF)),
@@ -517,6 +520,7 @@
       compiled_methods_filename_(nullptr),
       image_(false),
       is_host_(false),
+      driver_(nullptr),
       dump_stats_(false),
       dump_passes_(false),
       dump_timing_(false),
@@ -536,6 +540,8 @@
 
     if (kIsDebugBuild || (RUNNING_ON_VALGRIND != 0)) {
       delete runtime_;  // See field declaration for why this is manual.
+      delete driver_;
+      delete verification_results_;
     }
   }
 
@@ -1167,9 +1173,9 @@
       runtime_options.push_back(std::make_pair(runtime_args_[i], nullptr));
     }
 
-    verification_results_.reset(new VerificationResults(compiler_options_.get()));
+    verification_results_ = new VerificationResults(compiler_options_.get());
     callbacks_.reset(new QuickCompilerCallbacks(
-        verification_results_.get(),
+        verification_results_,
         &method_inliner_map_,
         image_ ?
             CompilerCallbacks::CallbackMode::kCompileBootImage :
@@ -1381,23 +1387,23 @@
       class_loader = class_linker->CreatePathClassLoader(self, class_path_files);
     }
 
-    driver_.reset(new CompilerDriver(compiler_options_.get(),
-                                     verification_results_.get(),
-                                     &method_inliner_map_,
-                                     compiler_kind_,
-                                     instruction_set_,
-                                     instruction_set_features_.get(),
-                                     image_,
-                                     image_classes_.release(),
-                                     compiled_classes_.release(),
-                                     nullptr,
-                                     thread_count_,
-                                     dump_stats_,
-                                     dump_passes_,
-                                     dump_cfg_file_name_,
-                                     compiler_phases_timings_.get(),
-                                     swap_fd_,
-                                     profile_file_));
+    driver_ = new CompilerDriver(compiler_options_.get(),
+                                 verification_results_,
+                                 &method_inliner_map_,
+                                 compiler_kind_,
+                                 instruction_set_,
+                                 instruction_set_features_.get(),
+                                 image_,
+                                 image_classes_.release(),
+                                 compiled_classes_.release(),
+                                 nullptr,
+                                 thread_count_,
+                                 dump_stats_,
+                                 dump_passes_,
+                                 dump_cfg_file_name_,
+                                 compiler_phases_timings_.get(),
+                                 swap_fd_,
+                                 profile_file_);
 
     driver_->CompileAll(class_loader, dex_files_, timings_);
   }
@@ -1499,7 +1505,7 @@
       oat_writer.reset(new OatWriter(dex_files_, image_file_location_oat_checksum,
                                      image_file_location_oat_data_begin,
                                      image_patch_delta,
-                                     driver_.get(),
+                                     driver_,
                                      image_writer_.get(),
                                      timings_,
                                      key_value_store_.get()));
@@ -1839,7 +1845,7 @@
     // Note: driver creation can fail when loading an invalid dex file.
     LOG(INFO) << "dex2oat took " << PrettyDuration(NanoTime() - start_ns_)
               << " (threads: " << thread_count_ << ") "
-              << ((Runtime::Current() != nullptr && driver_.get() != nullptr) ?
+              << ((Runtime::Current() != nullptr && driver_ != nullptr) ?
                   driver_->GetMemoryUsageString(kIsDebugBuild || VLOG_IS_ON(compiler)) :
                   "");
   }
@@ -1852,7 +1858,10 @@
 
   std::unique_ptr<SafeMap<std::string, std::string> > key_value_store_;
 
-  std::unique_ptr<VerificationResults> verification_results_;
+  // Not a unique_ptr as we want to just exit on non-debug builds, not bringing the compiler down
+  // in an orderly fashion. The destructor takes care of deleting this.
+  VerificationResults* verification_results_;
+
   DexFileToMethodInlinerMap method_inliner_map_;
   std::unique_ptr<QuickCompilerCallbacks> callbacks_;
 
@@ -1895,7 +1904,11 @@
   std::string android_root_;
   std::vector<const DexFile*> dex_files_;
   std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
-  std::unique_ptr<CompilerDriver> driver_;
+
+  // Not a unique_ptr as we want to just exit on non-debug builds, not bringing the driver down
+  // in an orderly fashion. The destructor takes care of deleting this.
+  CompilerDriver* driver_;
+
   std::vector<std::string> verbose_methods_;
   bool dump_stats_;
   bool dump_passes_;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 035ba44..7097a4a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2334,15 +2334,22 @@
     klass->SetIFields(ifields);
     klass->SetNumInstanceFields(num_ifields);
     DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
-    // Load methods.
-    if (it.NumDirectMethods() != 0) {
-      klass->SetDirectMethodsPtr(AllocArtMethodArray(self, it.NumDirectMethods()));
+    ArtMethod* const direct_methods = (it.NumDirectMethods() != 0)
+        ? AllocArtMethodArray(self, it.NumDirectMethods())
+        : nullptr;
+    ArtMethod* const virtual_methods = (it.NumVirtualMethods() != 0)
+        ? AllocArtMethodArray(self, it.NumVirtualMethods())
+        : nullptr;
+    {
+      // Used to get exclusion between with VisitNativeRoots so that no thread sees a length for
+      // one array with a pointer for a different array.
+      WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
+      // Load methods.
+      klass->SetDirectMethodsPtr(direct_methods);
+      klass->SetNumDirectMethods(it.NumDirectMethods());
+      klass->SetVirtualMethodsPtr(virtual_methods);
+      klass->SetNumVirtualMethods(it.NumVirtualMethods());
     }
-    klass->SetNumDirectMethods(it.NumDirectMethods());
-    if (it.NumVirtualMethods() != 0) {
-      klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, it.NumVirtualMethods()));
-    }
-    klass->SetNumVirtualMethods(it.NumVirtualMethods());
     size_t class_def_method_index = 0;
     uint32_t last_dex_method_index = DexFile::kDexNoIndex;
     size_t last_class_def_method_index = 0;
@@ -3321,8 +3328,11 @@
     self->AssertPendingOOMException();
     return nullptr;
   }
-  klass->SetDirectMethodsPtr(directs);
-  klass->SetNumDirectMethods(1u);
+  {
+    WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
+    klass->SetDirectMethodsPtr(directs);
+    klass->SetNumDirectMethods(1u);
+  }
   CreateProxyConstructor(klass, klass->GetDirectMethodUnchecked(0, image_pointer_size_));
 
   // Create virtual method using specified prototypes.
@@ -3337,8 +3347,11 @@
     self->AssertPendingOOMException();
     return nullptr;
   }
-  klass->SetVirtualMethodsPtr(virtuals);
-  klass->SetNumVirtualMethods(num_virtual_methods);
+  {
+    WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
+    klass->SetVirtualMethodsPtr(virtuals);
+    klass->SetNumVirtualMethods(num_virtual_methods);
+  }
   for (size_t i = 0; i < num_virtual_methods; ++i) {
     auto* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
     auto* prototype = h_methods->Get(i)->GetArtMethod();
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 11522d9..db09afb 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -453,7 +453,7 @@
   }
   mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
   uint32_t shorty_len = 0;
-  const char* shorty = method->GetShorty(&shorty_len);
+  const char* shorty = method->GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty(&shorty_len);
   JValue result;
   ArgArray arg_array(shorty, shorty_len);
   arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
@@ -483,7 +483,7 @@
   }
   mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj);
   uint32_t shorty_len = 0;
-  const char* shorty = method->GetShorty(&shorty_len);
+  const char* shorty = method->GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty(&shorty_len);
   JValue result;
   ArgArray arg_array(shorty, shorty_len);
   arg_array.BuildArgArrayFromJValues(soa, receiver, args);
@@ -514,7 +514,7 @@
     receiver = nullptr;
   }
   uint32_t shorty_len = 0;
-  const char* shorty = method->GetShorty(&shorty_len);
+  const char* shorty = method->GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty(&shorty_len);
   JValue result;
   ArgArray arg_array(shorty, shorty_len);
   arg_array.BuildArgArrayFromJValues(soa, receiver, args);
@@ -545,7 +545,7 @@
     receiver = nullptr;
   }
   uint32_t shorty_len = 0;
-  const char* shorty = method->GetShorty(&shorty_len);
+  const char* shorty = method->GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty(&shorty_len);
   JValue result;
   ArgArray arg_array(shorty, shorty_len);
   arg_array.BuildArgArrayFromVarArgs(soa, receiver, args);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 5274f9e..6e8f89c 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -546,6 +546,18 @@
   // a native peer!
   if (create_peer) {
     self->CreatePeer(thread_name, as_daemon, thread_group);
+    if (self->IsExceptionPending()) {
+      // We cannot keep the exception around, as we're deleting self. Try to be helpful and log it.
+      {
+        ScopedObjectAccess soa(self);
+        LOG(ERROR) << "Exception creating thread peer:";
+        LOG(ERROR) << self->GetException()->Dump();
+        self->ClearException();
+      }
+      runtime->GetThreadList()->Unregister(self);
+      // Unregister deletes self, no need to do this here.
+      return nullptr;
+    }
   } else {
     // These aren't necessary, but they improve diagnostics for unit tests & command-line tools.
     if (thread_name != nullptr) {
@@ -594,7 +606,9 @@
                                 WellKnownClasses::java_lang_Thread,
                                 WellKnownClasses::java_lang_Thread_init,
                                 thread_group, thread_name.get(), thread_priority, thread_is_daemon);
-  AssertNoPendingException();
+  if (IsExceptionPending()) {
+    return;
+  }
 
   Thread* self = this;
   DCHECK_EQ(self, Thread::Current());
@@ -1256,6 +1270,7 @@
   // Finish attaching the main thread.
   ScopedObjectAccess soa(Thread::Current());
   Thread::Current()->CreatePeer("main", false, runtime->GetMainThreadGroup());
+  Thread::Current()->AssertNoPendingException();
 
   Runtime::Current()->GetClassLinker()->RunRootClinits();
 }
diff --git a/test/044-proxy/expected.txt b/test/044-proxy/expected.txt
index bcce019..f86948a 100644
--- a/test/044-proxy/expected.txt
+++ b/test/044-proxy/expected.txt
@@ -93,3 +93,4 @@
 Got expected exception
 Proxy narrowed invocation return type passed
 5.8
+callback
diff --git a/test/044-proxy/native_proxy.cc b/test/044-proxy/native_proxy.cc
new file mode 100644
index 0000000..f168719
--- /dev/null
+++ b/test/044-proxy/native_proxy.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+
+#include "base/logging.h"
+
+namespace art {
+
+extern "C" JNIEXPORT void JNICALL Java_NativeProxy_nativeCall(
+    JNIEnv* env, jclass clazz ATTRIBUTE_UNUSED, jobject inf_ref) {
+  jclass native_inf_class = env->FindClass("NativeInterface");
+  CHECK(native_inf_class != nullptr);
+  jmethodID mid = env->GetMethodID(native_inf_class, "callback", "()V");
+  CHECK(mid != nullptr);
+  env->CallVoidMethod(inf_ref, mid);
+}
+
+}  // namespace art
diff --git a/test/044-proxy/src/Main.java b/test/044-proxy/src/Main.java
index 9580871..808a32d 100644
--- a/test/044-proxy/src/Main.java
+++ b/test/044-proxy/src/Main.java
@@ -28,5 +28,6 @@
         WrappedThrow.main(null);
         NarrowingTest.main(null);
         FloatSelect.main(null);
+        NativeProxy.main(null);
     }
 }
diff --git a/test/044-proxy/src/NativeProxy.java b/test/044-proxy/src/NativeProxy.java
new file mode 100644
index 0000000..954d6cc
--- /dev/null
+++ b/test/044-proxy/src/NativeProxy.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Test invoking a proxy method from native code.
+ */
+
+interface NativeInterface {
+    public void callback();
+}
+
+public class NativeProxy {
+
+    public static void main(String[] args) {
+        System.loadLibrary("arttest");
+
+        try {
+            NativeInterface inf = (NativeInterface)Proxy.newProxyInstance(
+                    NativeProxy.class.getClassLoader(),
+                    new Class[] { NativeInterface.class },
+                    new NativeInvocationHandler());
+
+            nativeCall(inf);
+        } catch (Exception exc) {
+            throw new RuntimeException(exc);
+        }
+    }
+
+    public static class NativeInvocationHandler implements InvocationHandler {
+        public Object invoke(final Object proxy,
+                             final Method method,
+                             final Object[] args) throws Throwable {
+            System.out.println(method.getName());
+            return null;
+        }
+    }
+
+    public static native void nativeCall(NativeInterface inf);
+}
diff --git a/test/529-checker-rtp-bug/expected.txt b/test/529-checker-rtp-bug/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/529-checker-rtp-bug/expected.txt
diff --git a/test/529-checker-rtp-bug/info.txt b/test/529-checker-rtp-bug/info.txt
new file mode 100644
index 0000000..852cd7c
--- /dev/null
+++ b/test/529-checker-rtp-bug/info.txt
@@ -0,0 +1 @@
+Test that we set the proper types for objects (b/25008765).
diff --git a/test/529-checker-rtp-bug/src/Main.java b/test/529-checker-rtp-bug/src/Main.java
new file mode 100644
index 0000000..cf5b601
--- /dev/null
+++ b/test/529-checker-rtp-bug/src/Main.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+final class Final { }
+
+public class Main {
+  // CHECK-START: Final Main.testKeepCheckCast(java.lang.Object, boolean) reference_type_propagation (after)
+  // CHECK:    [[Phi:l\d+]]     Phi
+  // CHECK:    [[Class:l\d+]]   LoadClass
+  // CHECK:                     CheckCast [ [[Phi]] [[Class]] ]
+  // CHECK:                     Return [ [[Phi]] ]
+
+  // CHECK-START: Final Main.testKeepCheckCast(java.lang.Object, boolean) instruction_simplifier_after_types (after)
+  // CHECK:    [[Phi:l\d+]]     Phi
+  // CHECK:    [[Class:l\d+]]   LoadClass
+  // CHECK:                     CheckCast
+  // CHECK:                     Return [ [[Phi]] ]
+  public static Final testKeepCheckCast(Object o, boolean cond) {
+    Object x = new Final();
+    while (cond) {
+      x = o;
+      cond = false;
+    }
+    return (Final) x;
+  }
+
+  public static void main(String[] args) {
+    try {
+      testKeepCheckCast(new Object(), true);
+      throw new Error("Expected check cast exception");
+    } catch (ClassCastException e) {
+      // expected
+    }
+  }
+}
diff --git a/test/Android.libarttest.mk b/test/Android.libarttest.mk
index 57d06c4..26eac4c 100644
--- a/test/Android.libarttest.mk
+++ b/test/Android.libarttest.mk
@@ -24,6 +24,7 @@
   004-ReferenceMap/stack_walk_refmap_jni.cc \
   004-StackWalk/stack_walk_jni.cc \
   004-UnsafeTest/unsafe_test.cc \
+  044-proxy/native_proxy.cc \
   051-thread/thread_test.cc \
   116-nodex2oat/nodex2oat.cc \
   117-nopatchoat/nopatchoat.cc \