ART: Rewrite JvmtiUniquePtr
Templatize it over the stored type. Add convenience function for
allocation.
Bug: 31455788
Test: m test-art-host
Change-Id: Idaf0a9170e95141e7a9878923aa93a0dbc80819c
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index a815a60..77ca9ce 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -1188,13 +1188,13 @@
ENSURE_NON_NULL(name_ptr);
switch (error) {
#define ERROR_CASE(e) case (JVMTI_ERROR_ ## e) : do { \
- jvmtiError res = CopyString(env, \
- "JVMTI_ERROR_"#e, \
- reinterpret_cast<unsigned char**>(name_ptr)); \
- if (res != OK) { \
+ jvmtiError res; \
+ JvmtiUniquePtr<char[]> copy = CopyString(env, "JVMTI_ERROR_"#e, &res); \
+ if (copy == nullptr) { \
*name_ptr = nullptr; \
return res; \
} else { \
+ *name_ptr = copy.release(); \
return OK; \
} \
} while (false)
@@ -1248,13 +1248,13 @@
ERROR_CASE(INVALID_ENVIRONMENT);
#undef ERROR_CASE
default: {
- jvmtiError res = CopyString(env,
- "JVMTI_ERROR_UNKNOWN",
- reinterpret_cast<unsigned char**>(name_ptr));
- if (res != OK) {
+ jvmtiError res;
+ JvmtiUniquePtr<char[]> copy = CopyString(env, "JVMTI_ERROR_UNKNOWN", &res);
+ if (copy == nullptr) {
*name_ptr = nullptr;
return res;
} else {
+ *name_ptr = copy.release();
return ERR(ILLEGAL_ARGUMENT);
}
}
diff --git a/runtime/openjdkjvmti/art_jvmti.h b/runtime/openjdkjvmti/art_jvmti.h
index 106165c..99139a1 100644
--- a/runtime/openjdkjvmti/art_jvmti.h
+++ b/runtime/openjdkjvmti/art_jvmti.h
@@ -33,6 +33,7 @@
#define ART_RUNTIME_OPENJDKJVMTI_ART_JVMTI_H_
#include <memory>
+#include <type_traits>
#include <jni.h>
@@ -86,6 +87,7 @@
return ret_value;
}
+template <typename T>
class JvmtiDeleter {
public:
JvmtiDeleter() : env_(nullptr) {}
@@ -95,9 +97,9 @@
JvmtiDeleter(JvmtiDeleter&&) = default;
JvmtiDeleter& operator=(const JvmtiDeleter&) = default;
- void operator()(unsigned char* ptr) const {
+ void operator()(T* ptr) const {
CHECK(env_ != nullptr);
- jvmtiError ret = env_->Deallocate(ptr);
+ jvmtiError ret = env_->Deallocate(reinterpret_cast<unsigned char*>(ptr));
CHECK(ret == ERR(NONE));
}
@@ -105,12 +107,65 @@
mutable jvmtiEnv* env_;
};
-using JvmtiUniquePtr = std::unique_ptr<unsigned char, JvmtiDeleter>;
+template <typename T>
+class JvmtiDeleter<T[]> {
+ public:
+ JvmtiDeleter() : env_(nullptr) {}
+ explicit JvmtiDeleter(jvmtiEnv* env) : env_(env) {}
+
+ JvmtiDeleter(JvmtiDeleter&) = default;
+ JvmtiDeleter(JvmtiDeleter&&) = default;
+ JvmtiDeleter& operator=(const JvmtiDeleter&) = default;
+
+ template <typename U>
+ void operator()(U* ptr) const {
+ CHECK(env_ != nullptr);
+ jvmtiError ret = env_->Deallocate(reinterpret_cast<unsigned char*>(ptr));
+ CHECK(ret == ERR(NONE));
+ }
+
+ private:
+ mutable jvmtiEnv* env_;
+};
+
+template <typename T>
+using JvmtiUniquePtr = std::unique_ptr<T, JvmtiDeleter<T>>;
template <typename T>
ALWAYS_INLINE
-static inline JvmtiUniquePtr MakeJvmtiUniquePtr(jvmtiEnv* env, T* mem) {
- return JvmtiUniquePtr(reinterpret_cast<unsigned char*>(mem), JvmtiDeleter(env));
+static inline JvmtiUniquePtr<T> MakeJvmtiUniquePtr(jvmtiEnv* env, T* mem) {
+ return JvmtiUniquePtr<T>(mem, JvmtiDeleter<T>(env));
+}
+
+template <typename T>
+ALWAYS_INLINE
+static inline JvmtiUniquePtr<T> MakeJvmtiUniquePtr(jvmtiEnv* env, unsigned char* mem) {
+ return JvmtiUniquePtr<T>(reinterpret_cast<T*>(mem), JvmtiDeleter<T>(env));
+}
+
+template <typename T>
+ALWAYS_INLINE
+static inline JvmtiUniquePtr<T> AllocJvmtiUniquePtr(jvmtiEnv* env, jvmtiError* error) {
+ unsigned char* tmp;
+ *error = env->Allocate(sizeof(T), &tmp);
+ if (*error != ERR(NONE)) {
+ return JvmtiUniquePtr<T>();
+ }
+ return JvmtiUniquePtr<T>(tmp, JvmtiDeleter<T>(env));
+}
+
+template <typename T>
+ALWAYS_INLINE
+static inline JvmtiUniquePtr<T> AllocJvmtiUniquePtr(jvmtiEnv* env,
+ size_t count,
+ jvmtiError* error) {
+ unsigned char* tmp;
+ *error = env->Allocate(sizeof(typename std::remove_extent<T>::type) * count, &tmp);
+ if (*error != ERR(NONE)) {
+ return JvmtiUniquePtr<T>();
+ }
+ return JvmtiUniquePtr<T>(reinterpret_cast<typename std::remove_extent<T>::type*>(tmp),
+ JvmtiDeleter<T>(env));
}
ALWAYS_INLINE
@@ -129,15 +184,12 @@
}
ALWAYS_INLINE
-static inline jvmtiError CopyString(jvmtiEnv* env, const char* src, unsigned char** copy) {
+static inline JvmtiUniquePtr<char[]> CopyString(jvmtiEnv* env, const char* src, jvmtiError* error) {
size_t len = strlen(src) + 1;
- unsigned char* buf;
- jvmtiError ret = env->Allocate(len, &buf);
- if (ret != ERR(NONE)) {
- return ret;
+ JvmtiUniquePtr<char[]> ret = AllocJvmtiUniquePtr<char[]>(env, len, error);
+ if (ret != nullptr) {
+ strcpy(ret.get(), src);
}
- strcpy(reinterpret_cast<char*>(buf), src);
- *copy = buf;
return ret;
}
diff --git a/runtime/openjdkjvmti/ti_class.cc b/runtime/openjdkjvmti/ti_class.cc
index a8a0ded..4282e38 100644
--- a/runtime/openjdkjvmti/ti_class.cc
+++ b/runtime/openjdkjvmti/ti_class.cc
@@ -673,18 +673,17 @@
return ERR(INVALID_CLASS);
}
- JvmtiUniquePtr sig_copy;
+ JvmtiUniquePtr<char[]> sig_copy;
if (signature_ptr != nullptr) {
std::string storage;
const char* descriptor = klass->GetDescriptor(&storage);
- unsigned char* tmp;
- jvmtiError ret = CopyString(env, descriptor, &tmp);
- if (ret != ERR(NONE)) {
+ jvmtiError ret;
+ sig_copy = CopyString(env, descriptor, &ret);
+ if (sig_copy == nullptr) {
return ret;
}
- sig_copy = MakeJvmtiUniquePtr(env, tmp);
- *signature_ptr = reinterpret_cast<char*>(tmp);
+ *signature_ptr = sig_copy.get();
}
if (generic_ptr != nullptr) {
@@ -700,12 +699,12 @@
oss << str_array->Get(i)->ToModifiedUtf8();
}
std::string output_string = oss.str();
- unsigned char* tmp;
- jvmtiError ret = CopyString(env, output_string.c_str(), &tmp);
- if (ret != ERR(NONE)) {
+ jvmtiError ret;
+ JvmtiUniquePtr<char[]> copy = CopyString(env, output_string.c_str(), &ret);
+ if (copy == nullptr) {
return ret;
}
- *generic_ptr = reinterpret_cast<char*>(tmp);
+ *generic_ptr = copy.release();
} else if (soa.Self()->IsExceptionPending()) {
// TODO: Should we report an error here?
soa.Self()->ClearException();
diff --git a/runtime/openjdkjvmti/ti_class_definition.h b/runtime/openjdkjvmti/ti_class_definition.h
index dbe5da2..3c251d4 100644
--- a/runtime/openjdkjvmti/ti_class_definition.h
+++ b/runtime/openjdkjvmti/ti_class_definition.h
@@ -46,7 +46,7 @@
std::string name;
jobject protection_domain;
jint dex_len;
- JvmtiUniquePtr dex_data;
+ JvmtiUniquePtr<unsigned char> dex_data;
art::ArraySlice<const unsigned char> original_dex_file;
ArtClassDefinition() = default;
diff --git a/runtime/openjdkjvmti/ti_field.cc b/runtime/openjdkjvmti/ti_field.cc
index 131e6c3..8c3f2ff 100644
--- a/runtime/openjdkjvmti/ti_field.cc
+++ b/runtime/openjdkjvmti/ti_field.cc
@@ -63,31 +63,29 @@
art::ScopedObjectAccess soa(art::Thread::Current());
art::ArtField* art_field = art::jni::DecodeArtField(field);
- JvmtiUniquePtr name_copy;
+ JvmtiUniquePtr<char[]> name_copy;
if (name_ptr != nullptr) {
const char* field_name = art_field->GetName();
if (field_name == nullptr) {
field_name = "<error>";
}
- unsigned char* tmp;
- jvmtiError ret = CopyString(env, field_name, &tmp);
- if (ret != ERR(NONE)) {
+ jvmtiError ret;
+ name_copy = CopyString(env, field_name, &ret);
+ if (name_copy == nullptr) {
return ret;
}
- name_copy = MakeJvmtiUniquePtr(env, tmp);
- *name_ptr = reinterpret_cast<char*>(tmp);
+ *name_ptr = name_copy.get();
}
- JvmtiUniquePtr signature_copy;
+ JvmtiUniquePtr<char[]> signature_copy;
if (signature_ptr != nullptr) {
const char* sig = art_field->GetTypeDescriptor();
- unsigned char* tmp;
- jvmtiError ret = CopyString(env, sig, &tmp);
- if (ret != ERR(NONE)) {
+ jvmtiError ret;
+ signature_copy = CopyString(env, sig, &ret);
+ if (signature_copy == nullptr) {
return ret;
}
- signature_copy = MakeJvmtiUniquePtr(env, tmp);
- *signature_ptr = reinterpret_cast<char*>(tmp);
+ *signature_ptr = signature_copy.get();
}
// TODO: Support generic signature.
@@ -102,12 +100,12 @@
oss << str_array->Get(i)->ToModifiedUtf8();
}
std::string output_string = oss.str();
- unsigned char* tmp;
- jvmtiError ret = CopyString(env, output_string.c_str(), &tmp);
- if (ret != ERR(NONE)) {
+ jvmtiError ret;
+ JvmtiUniquePtr<char[]> copy = CopyString(env, output_string.c_str(), &ret);
+ if (copy == nullptr) {
return ret;
}
- *generic_ptr = reinterpret_cast<char*>(tmp);
+ *generic_ptr = copy.release();
} else if (soa.Self()->IsExceptionPending()) {
// TODO: Should we report an error here?
soa.Self()->ClearException();
diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc
index a6cfcc1..bc73029 100644
--- a/runtime/openjdkjvmti/ti_method.cc
+++ b/runtime/openjdkjvmti/ti_method.cc
@@ -110,35 +110,32 @@
art::ArtMethod* art_method = art::jni::DecodeArtMethod(method);
art_method = art_method->GetInterfaceMethodIfProxy(art::kRuntimePointerSize);
- JvmtiUniquePtr name_copy;
+ JvmtiUniquePtr<char[]> name_copy;
if (name_ptr != nullptr) {
const char* method_name = art_method->GetName();
if (method_name == nullptr) {
method_name = "<error>";
}
- unsigned char* tmp;
- jvmtiError ret = CopyString(env, method_name, &tmp);
- if (ret != ERR(NONE)) {
+ jvmtiError ret;
+ name_copy = CopyString(env, method_name, &ret);
+ if (name_copy == nullptr) {
return ret;
}
- name_copy = MakeJvmtiUniquePtr(env, tmp);
- *name_ptr = reinterpret_cast<char*>(tmp);
+ *name_ptr = name_copy.get();
}
- JvmtiUniquePtr signature_copy;
+ JvmtiUniquePtr<char[]> signature_copy;
if (signature_ptr != nullptr) {
const art::Signature sig = art_method->GetSignature();
std::string str = sig.ToString();
- unsigned char* tmp;
- jvmtiError ret = CopyString(env, str.c_str(), &tmp);
- if (ret != ERR(NONE)) {
+ jvmtiError ret;
+ signature_copy = CopyString(env, str.c_str(), &ret);
+ if (signature_copy == nullptr) {
return ret;
}
- signature_copy = MakeJvmtiUniquePtr(env, tmp);
- *signature_ptr = reinterpret_cast<char*>(tmp);
+ *signature_ptr = signature_copy.get();
}
- // TODO: Support generic signature.
if (generic_ptr != nullptr) {
*generic_ptr = nullptr;
if (!art_method->GetDeclaringClass()->IsProxyClass()) {
@@ -150,12 +147,12 @@
oss << str_array->Get(i)->ToModifiedUtf8();
}
std::string output_string = oss.str();
- unsigned char* tmp;
- jvmtiError ret = CopyString(env, output_string.c_str(), &tmp);
- if (ret != ERR(NONE)) {
+ jvmtiError ret;
+ JvmtiUniquePtr<char[]> generic_copy = CopyString(env, output_string.c_str(), &ret);
+ if (generic_copy == nullptr) {
return ret;
}
- *generic_ptr = reinterpret_cast<char*>(tmp);
+ *generic_ptr = generic_copy.release();
} else if (soa.Self()->IsExceptionPending()) {
// TODO: Should we report an error here?
soa.Self()->ClearException();
diff --git a/runtime/openjdkjvmti/ti_properties.cc b/runtime/openjdkjvmti/ti_properties.cc
index 46b9e71..4f4f013 100644
--- a/runtime/openjdkjvmti/ti_properties.cc
+++ b/runtime/openjdkjvmti/ti_properties.cc
@@ -82,71 +82,69 @@
static constexpr const char* kPropertyLibraryPath = "java.library.path";
static constexpr const char* kPropertyClassPath = "java.class.path";
-static jvmtiError Copy(jvmtiEnv* env, const char* in, char** out) {
- unsigned char* data = nullptr;
- jvmtiError result = CopyString(env, in, &data);
- *out = reinterpret_cast<char*>(data);
- return result;
-}
-
jvmtiError PropertiesUtil::GetSystemProperties(jvmtiEnv* env,
jint* count_ptr,
char*** property_ptr) {
if (count_ptr == nullptr || property_ptr == nullptr) {
return ERR(NULL_POINTER);
}
- unsigned char* array_data;
- jvmtiError array_alloc_result = env->Allocate((kPropertiesSize + 2) * sizeof(char*), &array_data);
- if (array_alloc_result != ERR(NONE)) {
+ jvmtiError array_alloc_result;
+ JvmtiUniquePtr<char*[]> array_data_ptr = AllocJvmtiUniquePtr<char*[]>(env,
+ kPropertiesSize + 2,
+ &array_alloc_result);
+ if (array_data_ptr == nullptr) {
return array_alloc_result;
}
- JvmtiUniquePtr array_data_ptr = MakeJvmtiUniquePtr(env, array_data);
- char** array = reinterpret_cast<char**>(array_data);
- std::vector<JvmtiUniquePtr> property_copies;
+ std::vector<JvmtiUniquePtr<char[]>> property_copies;
{
- char* libpath_data;
- jvmtiError libpath_result = Copy(env, kPropertyLibraryPath, &libpath_data);
- if (libpath_result != ERR(NONE)) {
+ jvmtiError libpath_result;
+ JvmtiUniquePtr<char[]> libpath_data = CopyString(env, kPropertyLibraryPath, &libpath_result);
+ if (libpath_data == nullptr) {
return libpath_result;
}
- array[0] = libpath_data;
- property_copies.push_back(MakeJvmtiUniquePtr(env, libpath_data));
+ array_data_ptr.get()[0] = libpath_data.get();
+ property_copies.push_back(std::move(libpath_data));
}
{
- char* classpath_data;
- jvmtiError classpath_result = Copy(env, kPropertyClassPath, &classpath_data);
- if (classpath_result != ERR(NONE)) {
+ jvmtiError classpath_result;
+ JvmtiUniquePtr<char[]> classpath_data = CopyString(env, kPropertyClassPath, &classpath_result);
+ if (classpath_data == nullptr) {
return classpath_result;
}
- array[1] = classpath_data;
- property_copies.push_back(MakeJvmtiUniquePtr(env, classpath_data));
+ array_data_ptr.get()[1] = classpath_data.get();
+ property_copies.push_back(std::move(classpath_data));
}
for (size_t i = 0; i != kPropertiesSize; ++i) {
- char* data;
- jvmtiError data_result = Copy(env, kProperties[i][0], &data);
- if (data_result != ERR(NONE)) {
+ jvmtiError data_result;
+ JvmtiUniquePtr<char[]> data = CopyString(env, kProperties[i][0], &data_result);
+ if (data == nullptr) {
return data_result;
}
- array[i + 2] = data;
- property_copies.push_back(MakeJvmtiUniquePtr(env, data));
+ array_data_ptr.get()[i + 2] = data.get();
+ property_copies.push_back(std::move(data));
}
// Everything is OK, release the data.
- array_data_ptr.release();
+ *count_ptr = kPropertiesSize + 2;
+ *property_ptr = array_data_ptr.release();
for (auto& uptr : property_copies) {
uptr.release();
}
- *count_ptr = kPropertiesSize + 2;
- *property_ptr = array;
-
return ERR(NONE);
}
+static jvmtiError Copy(jvmtiEnv* env, const char* in, char** out) {
+ jvmtiError result;
+ JvmtiUniquePtr<char[]> data = CopyString(env, in, &result);
+ *out = data.release();
+ return result;
+}
+
jvmtiError PropertiesUtil::GetSystemProperty(jvmtiEnv* env,
const char* property,
char** value_ptr) {
diff --git a/runtime/openjdkjvmti/ti_redefine.cc b/runtime/openjdkjvmti/ti_redefine.cc
index 8436045..dcf999e 100644
--- a/runtime/openjdkjvmti/ti_redefine.cc
+++ b/runtime/openjdkjvmti/ti_redefine.cc
@@ -396,8 +396,8 @@
*error_msg_ = "Unable to get class signature!";
return ret;
}
- JvmtiUniquePtr generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
- JvmtiUniquePtr signature_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
+ JvmtiUniquePtr<char> generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
+ JvmtiUniquePtr<char> signature_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
std::unique_ptr<art::MemMap> map(MoveDataToMemMap(original_dex_location,
def.dex_len,
def.dex_data.get(),
diff --git a/runtime/openjdkjvmti/ti_thread.cc b/runtime/openjdkjvmti/ti_thread.cc
index f8f8fa6..788ac30 100644
--- a/runtime/openjdkjvmti/ti_thread.cc
+++ b/runtime/openjdkjvmti/ti_thread.cc
@@ -186,17 +186,17 @@
return ERR(INVALID_THREAD);
}
- JvmtiUniquePtr name_uptr;
+ JvmtiUniquePtr<char[]> name_uptr;
if (self != nullptr) {
// Have a native thread object, this thread is alive.
std::string name;
self->GetThreadName(name);
- jvmtiError name_result = CopyString(
- env, name.c_str(), reinterpret_cast<unsigned char**>(&info_ptr->name));
- if (name_result != ERR(NONE)) {
+ jvmtiError name_result;
+ name_uptr = CopyString(env, name.c_str(), &name_result);
+ if (name_uptr == nullptr) {
return name_result;
}
- name_uptr = MakeJvmtiUniquePtr(env, info_ptr->name);
+ info_ptr->name = name_uptr.get();
info_ptr->priority = self->GetNativePriority();
@@ -239,12 +239,12 @@
} else {
name_cstr = "";
}
- jvmtiError name_result = CopyString(
- env, name_cstr, reinterpret_cast<unsigned char**>(&info_ptr->name));
- if (name_result != ERR(NONE)) {
+ jvmtiError name_result;
+ name_uptr = CopyString(env, name_cstr, &name_result);
+ if (name_uptr == nullptr) {
return name_result;
}
- name_uptr = MakeJvmtiUniquePtr(env, info_ptr->name);
+ info_ptr->name = name_uptr.get();
}
// Priority.
diff --git a/runtime/openjdkjvmti/ti_threadgroup.cc b/runtime/openjdkjvmti/ti_threadgroup.cc
index 1423874..df14333 100644
--- a/runtime/openjdkjvmti/ti_threadgroup.cc
+++ b/runtime/openjdkjvmti/ti_threadgroup.cc
@@ -116,11 +116,12 @@
tmp_str = name_obj->ToModifiedUtf8();
tmp_cstr = tmp_str.c_str();
}
- jvmtiError result =
- CopyString(env, tmp_cstr, reinterpret_cast<unsigned char**>(&info_ptr->name));
- if (result != ERR(NONE)) {
+ jvmtiError result;
+ JvmtiUniquePtr<char[]> copy = CopyString(env, tmp_cstr, &result);
+ if (copy == nullptr) {
return result;
}
+ info_ptr->name = copy.release();
}
// Parent.
@@ -239,45 +240,38 @@
std::vector<art::ObjPtr<art::mirror::Object>> thread_groups;
GetChildThreadGroups(thread_group, &thread_groups);
- jthread* thread_data = nullptr;
- JvmtiUniquePtr peers_uptr;
+ JvmtiUniquePtr<jthread[]> peers_uptr;
if (!thread_peers.empty()) {
- unsigned char* data;
- jvmtiError res = env->Allocate(sizeof(jthread) * thread_peers.size(), &data);
- if (res != ERR(NONE)) {
+ jvmtiError res;
+ peers_uptr = AllocJvmtiUniquePtr<jthread[]>(env, thread_peers.size(), &res);
+ if (peers_uptr == nullptr) {
return res;
}
- thread_data = reinterpret_cast<jthread*>(data);
- peers_uptr = MakeJvmtiUniquePtr(env, data);
}
- jthreadGroup* group_data = nullptr;
+ JvmtiUniquePtr<jthreadGroup[]> group_uptr;
if (!thread_groups.empty()) {
- unsigned char* data;
- jvmtiError res = env->Allocate(sizeof(jthreadGroup) * thread_groups.size(), &data);
- if (res != ERR(NONE)) {
+ jvmtiError res;
+ group_uptr = AllocJvmtiUniquePtr<jthreadGroup[]>(env, thread_groups.size(), &res);
+ if (group_uptr == nullptr) {
return res;
}
- group_data = reinterpret_cast<jthreadGroup*>(data);
}
// Can't fail anymore from here on.
// Copy data into out buffers.
for (size_t i = 0; i != thread_peers.size(); ++i) {
- thread_data[i] = soa.AddLocalReference<jthread>(thread_peers[i]);
+ peers_uptr[i] = soa.AddLocalReference<jthread>(thread_peers[i]);
}
for (size_t i = 0; i != thread_groups.size(); ++i) {
- group_data[i] = soa.AddLocalReference<jthreadGroup>(thread_groups[i]);
+ group_uptr[i] = soa.AddLocalReference<jthreadGroup>(thread_groups[i]);
}
*thread_count_ptr = static_cast<jint>(thread_peers.size());
- *threads_ptr = thread_data;
+ *threads_ptr = peers_uptr.release();
*group_count_ptr = static_cast<jint>(thread_groups.size());
- *groups_ptr = group_data;
-
- // Everything's fine.
- peers_uptr.release();
+ *groups_ptr = group_uptr.release();
return ERR(NONE);
}