Merge "Fix thread status in THST chunk to use JDWP thread state." into dalvik-dev
diff --git a/Android.mk b/Android.mk
index a051152..46a7c1e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -181,6 +181,10 @@
@echo test-art-host-run-test-interpreter-$(1) PASSED
TEST_ART_HOST_RUN_TEST_INTERPRETER_TARGETS += test-art-host-run-test-interpreter-$(1)
+
+.PHONY: test-art-host-run-test-$(1)
+test-art-host-run-test-$(1): test-art-host-run-test-default-$(1) test-art-host-run-test-interpreter-$(1)
+
endef
$(foreach test, $(wildcard art/test/[0-9]*), $(eval $(call declare-test-art-host-run-test,$(notdir $(test)))))
@@ -228,6 +232,9 @@
@echo test-art-target-run-test-$(1) PASSED
TEST_ART_TARGET_RUN_TEST_TARGETS += test-art-target-run-test-$(1)
+
+test-art-run-test-$(1): test-art-host-run-test-$(1) test-art-target-run-test-$(1)
+
endef
$(foreach test, $(wildcard art/test/[0-9]*), $(eval $(call declare-test-art-target-run-test,$(notdir $(test)))))
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 634d3bc..b17df4e 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -671,7 +671,7 @@
if (klass.get() == NULL) {
image_classes_->erase(it++);
VLOG(compiler) << "Failed to find class " << descriptor;
- Thread::Current()->ClearException();
+ self->ClearException();
} else {
++it;
}
@@ -1472,7 +1472,7 @@
// Class couldn't be resolved, for example, super-class is in a different dex file. Don't
// attempt to resolve methods and fields when there is no declaring class.
CHECK(soa.Self()->IsExceptionPending());
- Thread::Current()->ClearException();
+ soa.Self()->ClearException();
resolve_fields_and_methods = false;
} else {
resolve_fields_and_methods = manager->GetCompiler()->IsImage();
@@ -1547,7 +1547,14 @@
if (klass == NULL) {
CHECK(soa.Self()->IsExceptionPending());
- Thread::Current()->ClearException();
+ mirror::Throwable* exception = soa.Self()->GetException(NULL);
+ VLOG(compiler) << "Exception during type resolution: " << exception->Dump();
+ if (strcmp(ClassHelper(exception->GetClass()).GetDescriptor(),
+ "Ljava/lang/OutOfMemoryError;") == 0) {
+ // There's little point continuing compilation if the heap is exhausted.
+ LOG(FATAL) << "Out of memory during type resolution for compilation";
+ }
+ soa.Self()->ClearException();
}
}
@@ -1700,12 +1707,13 @@
"Landroid/net/NetworkInfo;", // Calls java.util.EnumMap.<init> -> java.lang.Enum.getSharedConstants -> System.identityHashCode.
"Landroid/net/Proxy;", // Calls regex.Pattern.compile -..-> regex.Pattern.compileImpl.
"Landroid/net/SSLCertificateSocketFactory;", // Requires javax.net.ssl.HttpsURLConnection.
- "Landroid/net/Uri;", // Calls Class.getSimpleName -> Class.isAnonymousClass -> Class.getDex.
"Landroid/net/Uri$AbstractHierarchicalUri;", // Requires Uri.
"Landroid/net/Uri$HierarchicalUri;", // Requires Uri.
"Landroid/net/Uri$OpaqueUri;", // Requires Uri.
"Landroid/net/Uri$StringUri;", // Requires Uri.
+ "Landroid/net/Uri;", // Calls Class.getSimpleName -> Class.isAnonymousClass -> Class.getDex.
"Landroid/net/WebAddress;", // Calls regex.Pattern.compile -..-> regex.Pattern.compileImpl.
+ "Landroid/net/wifi/WifiNative;", // Calls new LocalLog -> new Time -> TimeZone -> Pattern.compile.
"Landroid/nfc/NdefRecord;", // Calls String.getBytes -> java.nio.charset.Charset.
"Landroid/opengl/EGL14;", // Calls android.opengl.EGL14._nativeClassInit.
"Landroid/opengl/GLES10;", // Calls android.opengl.GLES10._nativeClassInit.
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 8ec13bf..5c96d74 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -828,6 +828,19 @@
timings.StartSplit("dex2oat Setup");
LOG(INFO) << "dex2oat: " << oat_location;
+ if (image) {
+ bool has_compiler_filter = false;
+ for (const char* r : runtime_args) {
+ if (strncmp(r, "-compiler-filter:", 17) == 0) {
+ has_compiler_filter = true;
+ break;
+ }
+ }
+ if (!has_compiler_filter) {
+ runtime_args.push_back("-compiler-filter:everything");
+ }
+ }
+
Runtime::Options options;
options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
std::vector<const DexFile*> boot_class_path;
@@ -865,9 +878,6 @@
// If we're doing the image, override the compiler filter to force full compilation. Must be
// done ahead of WellKnownClasses::Init that causes verification. Note: doesn't force
// compilation of class initializers.
- if (image) {
- Runtime::Current()->SetCompilerFilter(Runtime::kEverything);
- }
// Whilst we're in native take the opportunity to initialize well known classes.
WellKnownClasses::Init(self->GetJniEnv());
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index cd4a720..37b62ad 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1217,11 +1217,15 @@
size_t class_size) {
DCHECK_GE(class_size, sizeof(mirror::Class));
gc::Heap* heap = Runtime::Current()->GetHeap();
- SirtRef<mirror::Class> klass(self,
- heap->AllocObject(self, java_lang_Class, class_size)->AsClass());
+ mirror::Object* k = heap->AllocObject(self, java_lang_Class, class_size);
+ if (UNLIKELY(k == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
+ mirror::Class* klass = k->AsClass();
klass->SetPrimitiveType(Primitive::kPrimNot); // default to not being primitive
klass->SetClassSize(class_size);
- return klass.get();
+ return klass;
}
mirror::Class* ClassLinker::AllocClass(Thread* self, size_t class_size) {
@@ -1388,6 +1392,10 @@
} else {
klass.reset(AllocClass(self, SizeOfClass(dex_file, dex_class_def)));
}
+ if (UNLIKELY(klass.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // Expect an OOME.
+ return NULL;
+ }
klass->SetDexCache(FindDexCache(dex_file));
LoadClass(dex_file, dex_class_def, klass, class_loader);
// Check for a pending exception during load
@@ -1725,18 +1733,37 @@
ClassDataItemIterator it(dex_file, class_data);
Thread* self = Thread::Current();
if (it.NumStaticFields() != 0) {
- klass->SetSFields(AllocArtFieldArray(self, it.NumStaticFields()));
+ mirror::ObjectArray<mirror::ArtField>* statics = AllocArtFieldArray(self, it.NumStaticFields());
+ if (UNLIKELY(statics == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return;
+ }
+ klass->SetSFields(statics);
}
if (it.NumInstanceFields() != 0) {
- klass->SetIFields(AllocArtFieldArray(self, it.NumInstanceFields()));
+ mirror::ObjectArray<mirror::ArtField>* fields =
+ AllocArtFieldArray(self, it.NumInstanceFields());
+ if (UNLIKELY(fields == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return;
+ }
+ klass->SetIFields(fields);
}
for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
SirtRef<mirror::ArtField> sfield(self, AllocArtField(self));
+ if (UNLIKELY(sfield.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return;
+ }
klass->SetStaticField(i, sfield.get());
LoadField(dex_file, it, klass, sfield);
}
for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
SirtRef<mirror::ArtField> ifield(self, AllocArtField(self));
+ if (UNLIKELY(ifield.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return;
+ }
klass->SetInstanceField(i, ifield.get());
LoadField(dex_file, it, klass, ifield);
}
@@ -1749,15 +1776,31 @@
// Load methods.
if (it.NumDirectMethods() != 0) {
// TODO: append direct methods to class object
- klass->SetDirectMethods(AllocArtMethodArray(self, it.NumDirectMethods()));
+ mirror::ObjectArray<mirror::ArtMethod>* directs =
+ AllocArtMethodArray(self, it.NumDirectMethods());
+ if (UNLIKELY(directs == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return;
+ }
+ klass->SetDirectMethods(directs);
}
if (it.NumVirtualMethods() != 0) {
// TODO: append direct methods to class object
- klass->SetVirtualMethods(AllocArtMethodArray(self, it.NumVirtualMethods()));
+ mirror::ObjectArray<mirror::ArtMethod>* virtuals =
+ AllocArtMethodArray(self, it.NumVirtualMethods());
+ if (UNLIKELY(virtuals == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return;
+ }
+ klass->SetVirtualMethods(virtuals);
}
size_t class_def_method_index = 0;
for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
SirtRef<mirror::ArtMethod> method(self, LoadMethod(self, dex_file, it, klass));
+ if (UNLIKELY(method.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return;
+ }
klass->SetDirectMethod(i, method.get());
if (oat_class.get() != NULL) {
LinkCode(method, oat_class.get(), class_def_method_index);
@@ -1767,6 +1810,10 @@
}
for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
SirtRef<mirror::ArtMethod> method(self, LoadMethod(self, dex_file, it, klass));
+ if (UNLIKELY(method.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return;
+ }
klass->SetVirtualMethod(i, method.get());
DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
if (oat_class.get() != NULL) {
@@ -1786,13 +1833,17 @@
}
mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file,
- const ClassDataItemIterator& it,
- SirtRef<mirror::Class>& klass) {
+ const ClassDataItemIterator& it,
+ SirtRef<mirror::Class>& klass) {
uint32_t dex_method_idx = it.GetMemberIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
StringPiece method_name(dex_file.GetMethodName(method_id));
mirror::ArtMethod* dst = AllocArtMethod(self);
+ if (UNLIKELY(dst == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
DCHECK(dst->IsArtMethod()) << PrettyDescriptor(dst->GetClass());
const char* old_cause = self->StartAssertNoThreadSuspension("LoadMethod");
@@ -1846,6 +1897,7 @@
void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
Thread* self = Thread::Current();
SirtRef<mirror::DexCache> dex_cache(self, AllocDexCache(self, dex_file));
+ CHECK(dex_cache.get() != NULL) << "Failed to allocate dex cache for " << dex_file.GetLocation();
AppendToBootClassPath(dex_file, dex_cache);
}
@@ -1891,6 +1943,7 @@
// suspend all threads and another thread may need the dex_lock_ to
// get to a suspend point.
SirtRef<mirror::DexCache> dex_cache(self, AllocDexCache(self, dex_file));
+ CHECK(dex_cache.get() != NULL) << "Failed to allocate dex cache for " << dex_file.GetLocation();
{
WriterMutexLock mu(self, dex_lock_);
if (IsDexFileRegisteredLocked(dex_file)) {
@@ -1939,7 +1992,11 @@
}
mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type type) {
- return InitializePrimitiveClass(AllocClass(self, sizeof(mirror::Class)), type);
+ mirror::Class* klass = AllocClass(self, sizeof(mirror::Class));
+ if (UNLIKELY(klass == NULL)) {
+ return NULL;
+ }
+ return InitializePrimitiveClass(klass, type);
}
mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class, Primitive::Type type) {
@@ -2574,7 +2631,10 @@
Thread* self = Thread::Current();
SirtRef<mirror::Class> klass(self, AllocClass(self, GetClassRoot(kJavaLangClass),
sizeof(mirror::SynthesizedProxyClass)));
- CHECK(klass.get() != NULL);
+ if (klass.get() == NULL) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
DCHECK(klass->GetClass() != NULL);
klass->SetObjectSize(sizeof(mirror::Proxy));
klass->SetAccessFlags(kAccClassIsProxy | kAccPublic | kAccFinal);
@@ -2589,31 +2649,72 @@
klass->SetDexTypeIndex(DexFile::kDexNoIndex16);
// Instance fields are inherited, but we add a couple of static fields...
- klass->SetSFields(AllocArtFieldArray(self, 2));
+ {
+ mirror::ObjectArray<mirror::ArtField>* sfields = AllocArtFieldArray(self, 2);
+ if (UNLIKELY(sfields == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
+ klass->SetSFields(sfields);
+ }
// 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by
// our proxy, so Class.getInterfaces doesn't return the flattened set.
SirtRef<mirror::ArtField> interfaces_sfield(self, AllocArtField(self));
+ if (UNLIKELY(interfaces_sfield.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
klass->SetStaticField(0, interfaces_sfield.get());
interfaces_sfield->SetDexFieldIndex(0);
interfaces_sfield->SetDeclaringClass(klass.get());
interfaces_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
// 2. Create a static field 'throws' that holds exceptions thrown by our methods.
SirtRef<mirror::ArtField> throws_sfield(self, AllocArtField(self));
+ if (UNLIKELY(throws_sfield.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
klass->SetStaticField(1, throws_sfield.get());
throws_sfield->SetDexFieldIndex(1);
throws_sfield->SetDeclaringClass(klass.get());
throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
// Proxies have 1 direct method, the constructor
- klass->SetDirectMethods(AllocArtMethodArray(self, 1));
- klass->SetDirectMethod(0, CreateProxyConstructor(self, klass, proxy_class));
+ {
+ mirror::ObjectArray<mirror::ArtMethod>* directs =
+ AllocArtMethodArray(self, 1);
+ if (UNLIKELY(directs == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
+ klass->SetDirectMethods(directs);
+ mirror::ArtMethod* constructor = CreateProxyConstructor(self, klass, proxy_class);
+ if (UNLIKELY(constructor == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
+ klass->SetDirectMethod(0, constructor);
+ }
// Create virtual method using specified prototypes
size_t num_virtual_methods = methods->GetLength();
- klass->SetVirtualMethods(AllocArtMethodArray(self, num_virtual_methods));
+ {
+ mirror::ObjectArray<mirror::ArtMethod>* virtuals =
+ AllocArtMethodArray(self, num_virtual_methods);
+ if (UNLIKELY(virtuals == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
+ klass->SetVirtualMethods(virtuals);
+ }
for (size_t i = 0; i < num_virtual_methods; ++i) {
SirtRef<mirror::ArtMethod> prototype(self, methods->Get(i));
- klass->SetVirtualMethod(i, CreateProxyMethod(self, klass, prototype));
+ mirror::ArtMethod* clone = CreateProxyMethod(self, klass, prototype);
+ if (UNLIKELY(clone == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
+ klass->SetVirtualMethod(i, clone);
}
klass->SetSuperClass(proxy_class); // The super class is java.lang.reflect.Proxy
@@ -2701,6 +2802,10 @@
// code_ too)
mirror::ArtMethod* constructor =
down_cast<mirror::ArtMethod*>(proxy_constructor->Clone(self));
+ if (constructor == NULL) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
// Make this constructor public and fix the class to be our Proxy version
constructor->SetAccessFlags((constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic);
constructor->SetDeclaringClass(klass.get());
@@ -2725,6 +2830,10 @@
// We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
// as necessary
mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(prototype->Clone(self));
+ if (UNLIKELY(method == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return NULL;
+ }
// Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to
// the intersection of throw exceptions as defined in Proxy
@@ -3277,6 +3386,10 @@
// TODO: do not assign to the vtable field until it is fully constructed.
SirtRef<mirror::ObjectArray<mirror::ArtMethod> >
vtable(self, klass->GetSuperClass()->GetVTable()->CopyOf(self, max_count));
+ if (UNLIKELY(vtable.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
// See if any of our virtual methods override the superclass.
MethodHelper local_mh(NULL, this);
MethodHelper super_mh(NULL, this);
@@ -3320,6 +3433,10 @@
CHECK_LE(actual_count, max_count);
if (actual_count < max_count) {
vtable.reset(vtable->CopyOf(self, actual_count));
+ if (UNLIKELY(vtable.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
}
klass->SetVTable(vtable.get());
} else {
@@ -3331,6 +3448,10 @@
}
SirtRef<mirror::ObjectArray<mirror::ArtMethod> >
vtable(self, AllocArtMethodArray(self, num_virtual_methods));
+ if (UNLIKELY(vtable.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
for (size_t i = 0; i < num_virtual_methods; ++i) {
mirror::ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i);
vtable->Set(i, virtual_method);
@@ -3381,6 +3502,10 @@
}
Thread* self = Thread::Current();
SirtRef<mirror::IfTable> iftable(self, AllocIfTable(self, ifcount));
+ if (UNLIKELY(iftable.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
if (super_ifcount != 0) {
mirror::IfTable* super_iftable = klass->GetSuperClass()->GetIfTable();
for (size_t i = 0; i < super_ifcount; i++) {
@@ -3432,6 +3557,10 @@
// Shrink iftable in case duplicates were found
if (idx < ifcount) {
iftable.reset(down_cast<mirror::IfTable*>(iftable->CopyOf(self, idx * mirror::IfTable::kMax)));
+ if (UNLIKELY(iftable.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
ifcount = idx;
} else {
CHECK_EQ(idx, ifcount);
@@ -3451,6 +3580,10 @@
if (num_methods > 0) {
mirror::ObjectArray<mirror::ArtMethod>* method_array =
AllocArtMethodArray(self, num_methods);
+ if (UNLIKELY(method_array == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
iftable->SetMethodArray(i, method_array);
mirror::ObjectArray<mirror::ArtMethod>* vtable = klass->GetVTableDuringLinking();
for (size_t j = 0; j < num_methods; ++j) {
@@ -3491,8 +3624,16 @@
}
}
if (miranda_method.get() == NULL) {
- // point the interface table at a phantom slot
+ // Point the interface table at a phantom slot.
miranda_method.reset(down_cast<mirror::ArtMethod*>(interface_method->Clone(self)));
+ if (UNLIKELY(miranda_method.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
+#ifdef MOVING_GARBAGE_COLLECTOR
+ // TODO: If a methods move then the miranda_list may hold stale references.
+ UNIMPLEMENTED(FATAL);
+#endif
miranda_list.push_back(miranda_method.get());
}
method_array->Set(j, miranda_method.get());
@@ -3503,9 +3644,17 @@
if (!miranda_list.empty()) {
int old_method_count = klass->NumVirtualMethods();
int new_method_count = old_method_count + miranda_list.size();
- klass->SetVirtualMethods((old_method_count == 0)
- ? AllocArtMethodArray(self, new_method_count)
- : klass->GetVirtualMethods()->CopyOf(self, new_method_count));
+ mirror::ObjectArray<mirror::ArtMethod>* virtuals;
+ if (old_method_count == 0) {
+ virtuals = AllocArtMethodArray(self, new_method_count);
+ } else {
+ virtuals = klass->GetVirtualMethods()->CopyOf(self, new_method_count);
+ }
+ if (UNLIKELY(virtuals == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
+ klass->SetVirtualMethods(virtuals);
SirtRef<mirror::ObjectArray<mirror::ArtMethod> >
vtable(self, klass->GetVTableDuringLinking());
@@ -3513,6 +3662,10 @@
int old_vtable_count = vtable->GetLength();
int new_vtable_count = old_vtable_count + miranda_list.size();
vtable.reset(vtable->CopyOf(self, new_vtable_count));
+ if (UNLIKELY(vtable.get() == NULL)) {
+ CHECK(self->IsExceptionPending()); // OOME.
+ return false;
+ }
for (size_t i = 0; i < miranda_list.size(); ++i) {
mirror::ArtMethod* method = miranda_list[i];
// Leave the declaring class alone as type indices are relative to it
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 28a91dd..efaa183 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -79,10 +79,10 @@
Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
int32_t IdentityHashCode() const {
- #ifdef MOVING_GARBAGE_COLLECTOR
+#ifdef MOVING_GARBAGE_COLLECTOR
// TODO: we'll need to use the Object's internal concept of identity
- UNIMPLEMENTED(FATAL);
- #endif
+ UNIMPLEMENTED(FATAL);
+#endif
return reinterpret_cast<int32_t>(this);
}
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 6f22618..abc88a3 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -135,7 +135,9 @@
template<class T>
inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length);
- Copy(this, 0, new_array, 0, std::min(GetLength(), new_length));
+ if (LIKELY(new_array != NULL)) {
+ Copy(this, 0, new_array, 0, std::min(GetLength(), new_length));
+ }
return new_array;
}
diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc
index 1ad0182..a505ed0 100644
--- a/runtime/mirror/stack_trace_element.cc
+++ b/runtime/mirror/stack_trace_element.cc
@@ -44,14 +44,16 @@
int32_t line_number) {
StackTraceElement* trace =
down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject(self));
- trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
- const_cast<String*>(declaring_class), false);
- trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
- const_cast<String*>(method_name), false);
- trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
- const_cast<String*>(file_name), false);
- trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_),
- line_number, false);
+ if (LIKELY(trace != NULL)) {
+ trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
+ const_cast<String*>(declaring_class), false);
+ trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
+ const_cast<String*>(method_name), false);
+ trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
+ const_cast<String*>(file_name), false);
+ trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_),
+ line_number, false);
+ }
return trace;
}
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index c64caa8..54ba3b0 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -137,7 +137,7 @@
return string;
}
- String* String::AllocFromModifiedUtf8(Thread* self, const char* utf) {
+String* String::AllocFromModifiedUtf8(Thread* self, const char* utf) {
if (utf == NULL) {
return NULL;
}
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index b0f67c4..5fc8bd5 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -74,9 +74,6 @@
descriptor += ClassHelper(element_class).GetDescriptor();
mirror::Class* array_class = class_linker->FindClass(descriptor.c_str(), NULL);
mirror::Array* result = mirror::Array::Alloc(soa.Self(), array_class, length);
- if (result == NULL) {
- return NULL;
- }
return soa.AddLocalReference<jobject>(result);
}
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 5679d4e..09cbd0b 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -704,14 +704,8 @@
CHECK(host_prefix_.empty()) << host_prefix_;
- // Pre-allocate an OutOfMemoryError for the double-OOME case.
- Thread* self = Thread::Current();
- self->ThrowNewException(ThrowLocation(), "Ljava/lang/OutOfMemoryError;",
- "OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available");
- pre_allocated_OutOfMemoryError_ = self->GetException(NULL);
- self->ClearException();
-
// Restore main thread state to kNative as expected by native code.
+ Thread* self = Thread::Current();
self->TransitionFromRunnableToSuspended(kNative);
started_ = true;
@@ -906,7 +900,7 @@
// Set us to runnable so tools using a runtime can allocate and GC by default
self->TransitionFromSuspendedToRunnable();
- // Now we're attached, we can take the heap lock and validate the heap.
+ // Now we're attached, we can take the heap locks and validate the heap.
GetHeap()->EnableObjectValidation();
CHECK_GE(GetHeap()->GetContinuousSpaces().size(), 1U);
@@ -929,6 +923,12 @@
false, false, 0);
}
+ // Pre-allocate an OutOfMemoryError for the double-OOME case.
+ self->ThrowNewException(ThrowLocation(), "Ljava/lang/OutOfMemoryError;",
+ "OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack available");
+ pre_allocated_OutOfMemoryError_ = self->GetException(NULL);
+ self->ClearException();
+
VLOG(startup) << "Runtime::Init exiting";
return true;
}
@@ -1123,6 +1123,13 @@
thread_list_->Unregister(self);
}
+ mirror::Throwable* Runtime::GetPreAllocatedOutOfMemoryError() const {
+ if (pre_allocated_OutOfMemoryError_ == NULL) {
+ LOG(ERROR) << "Failed to return pre-allocated OOME";
+ }
+ return pre_allocated_OutOfMemoryError_;
+}
+
void Runtime::VisitConcurrentRoots(RootVisitor* visitor, void* arg, bool only_dirty,
bool clean_dirty) {
if (!only_dirty || intern_table_->IsDirty()) {
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 50108ac..21161a0 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -287,9 +287,8 @@
return monitor_list_;
}
- mirror::Throwable* GetPreAllocatedOutOfMemoryError() {
- return pre_allocated_OutOfMemoryError_;
- }
+ mirror::Throwable* GetPreAllocatedOutOfMemoryError() const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const std::vector<std::string>& GetProperties() const {
return properties_;
diff --git a/test/Android.mk b/test/Android.mk
index 596c411..6f498e8 100644
--- a/test/Android.mk
+++ b/test/Android.mk
@@ -133,6 +133,12 @@
&& echo test-art-host-oat-interpreter-$(1) PASSED || (echo test-art-host-oat-interpreter-$(1) FAILED && exit 1)
$(hide) rm -r /tmp/android-data/test-art-host-oat-interpreter-$(1)
+.PHONY: test-art-host-oat-$(1)
+test-art-host-oat-$(1): test-art-host-oat-default-$(1) test-art-host-oat-interpreter-$(1)
+
+.PHONY: test-art-oat-$(1)
+test-art-oat-$(1): test-art-host-oat-$(1) test-art-target-oat-$(1)
+
ART_TEST_TARGET_OAT_TARGETS += test-art-target-oat-$(1)
ART_TEST_HOST_OAT_DEFAULT_TARGETS += test-art-host-oat-default-$(1)
ART_TEST_HOST_OAT_INTERPRETER_TARGETS += test-art-host-oat-interpreter-$(1)