summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2015-12-08 03:20:54 -0800
committerSteve Kondik <steve@cyngn.com>2015-12-08 03:20:54 -0800
commit875ffee6f23971466f3655a9e1e73ba6a1dc0393 (patch)
tree07b88bebf3229933589c6f98fe8ff2ae051c1181
parent29bd42b5eb0382360e3a8cb646ccf4de4b3b1d5a (diff)
parent1dff62f822392dd3f95ec23ba578bf42430ba112 (diff)
downloadart-875ffee6f23971466f3655a9e1e73ba6a1dc0393.zip
art-875ffee6f23971466f3655a9e1e73ba6a1dc0393.tar.gz
art-875ffee6f23971466f3655a9e1e73ba6a1dc0393.tar.bz2
Merge tag 'android-6.0.1_r3' of https://android.googlesource.com/platform/art into HEAD
Android 6.0.1 release 3 Change-Id: I23fd56f2c1a3e8e8b993a151a794e18f3569912e
-rw-r--r--compiler/jit/jit_compiler.cc33
-rw-r--r--compiler/optimizing/reference_type_propagation.cc4
-rw-r--r--dex2oat/dex2oat.cc63
-rw-r--r--runtime/class_linker.cc37
-rw-r--r--runtime/reflection.cc8
-rw-r--r--runtime/thread.cc17
-rw-r--r--test/044-proxy/expected.txt1
-rw-r--r--test/044-proxy/native_proxy.cc32
-rw-r--r--test/044-proxy/src/Main.java1
-rw-r--r--test/044-proxy/src/NativeProxy.java62
-rw-r--r--test/529-checker-rtp-bug/expected.txt0
-rw-r--r--test/529-checker-rtp-bug/info.txt1
-rw-r--r--test/529-checker-rtp-bug/src/Main.java48
-rw-r--r--test/Android.libarttest.mk1
14 files changed, 264 insertions, 44 deletions
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 @@ JitCompiler::JitCompiler() : total_time_(0) {
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 @@ bool ReferenceTypePropagation::UpdateNullability(HInstruction* instr) {
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 18a5a45..03679fa 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -436,8 +436,10 @@ class WatchDog {
// Debug builds are slower so they have larger timeouts.
static constexpr int64_t kSlowdownFactor = kIsDebugBuild ? 5U : 1U;
- // 60 minutes scaled by kSlowdownFactor.
- static constexpr int64_t kWatchDogTimeoutSeconds = kSlowdownFactor * 60 * 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_;
@@ -505,6 +507,7 @@ class Dex2Oat FINAL {
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)),
@@ -520,6 +523,7 @@ class Dex2Oat FINAL {
compiled_methods_filename_(nullptr),
image_(false),
is_host_(false),
+ driver_(nullptr),
dump_stats_(false),
dump_passes_(false),
dump_timing_(false),
@@ -539,6 +543,8 @@ class Dex2Oat FINAL {
if (kIsDebugBuild || (RUNNING_ON_VALGRIND != 0)) {
delete runtime_; // See field declaration for why this is manual.
+ delete driver_;
+ delete verification_results_;
}
}
@@ -1182,9 +1188,9 @@ class Dex2Oat FINAL {
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 :
@@ -1396,23 +1402,23 @@ class Dex2Oat FINAL {
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_);
}
@@ -1514,7 +1520,7 @@ class Dex2Oat FINAL {
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()));
@@ -1854,7 +1860,7 @@ class Dex2Oat FINAL {
// 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)) :
"");
}
@@ -1867,7 +1873,10 @@ class Dex2Oat FINAL {
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_;
@@ -1910,7 +1919,11 @@ class Dex2Oat FINAL {
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 9ca6492..d0e8e68 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2334,15 +2334,22 @@ void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file,
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()));
- }
- klass->SetNumDirectMethods(it.NumDirectMethods());
- if (it.NumVirtualMethods() != 0) {
- klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, it.NumVirtualMethods()));
+ 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->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 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
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 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
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 @@ JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject o
}
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 @@ JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject o
}
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 @@ JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnab
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 @@ JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnab
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 @@ Thread* Thread::Attach(const char* thread_name, bool as_daemon, jobject thread_g
// 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 @@ void Thread::CreatePeer(const char* name, bool as_daemon, jobject thread_group)
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 @@ void Thread::FinishStartup() {
// 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 @@ Invocation of public abstract java.lang.String NarrowingTest$I2.foo()
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 @@ public class Main {
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 @@ LIBARTTEST_COMMON_SRC_FILES := \
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 \