ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
CHECK(obj != nullptr);
for (jint i = 0; i < reps; ++i) {
- jobject ref = soa.Env()->AddLocalReference<jobject>(obj.Ptr());
+ jobject ref = soa.Env()->AddLocalReference<jobject>(obj);
soa.Env()->DeleteLocalRef(ref);
}
}
ScopedObjectAccess soa(env);
ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
CHECK(obj != nullptr);
- jobject ref = soa.Env()->AddLocalReference<jobject>(obj.Ptr());
+ jobject ref = soa.Env()->AddLocalReference<jobject>(obj);
for (jint i = 0; i < reps; ++i) {
CHECK_EQ(soa.Decode<mirror::Object>(ref), obj);
}
--- /dev/null
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef ART_RUNTIME_BASE_DUMPABLE_INL_H_
+#define ART_RUNTIME_BASE_DUMPABLE_INL_H_
+
+#include "base/dumpable.h"
+#include "base/mutex.h"
+#include "thread-inl.h"
+
+namespace art {
+
+template<typename T>
+inline std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs) {
+ Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
+ rhs.Dump(os);
+ return os;
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_BASE_DUMPABLE_INL_H_
#include <ostream>
#include "base/macros.h"
+#include "base/mutex.h"
namespace art {
return os;
}
+template<typename T>
+class MutatorLockedDumpable {
+ public:
+ explicit MutatorLockedDumpable(T& value) REQUIRES_SHARED(Locks::mutator_lock_) : value_(value) {}
+
+ void Dump(std::ostream& os) const REQUIRES_SHARED(Locks::mutator_lock_) {
+ value_.Dump(os);
+ }
+
+ private:
+ const T& value_;
+
+ DISALLOW_COPY_AND_ASSIGN(MutatorLockedDumpable);
+};
+
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs)
+ // TODO: should be REQUIRES_SHARED(Locks::mutator_lock_) however annotalysis
+ // currently fails for this.
+ NO_THREAD_SAFETY_ANALYSIS;
+
} // namespace art
#endif // ART_RUNTIME_BASE_DUMPABLE_H_
// Make it a global ref and return.
ScopedLocalRef<jobject> local_ref(
- soa.Env(), soa.Env()->AddLocalReference<jobject>(h_path_class_loader.Get()));
+ soa.Env(), soa.Env()->AddLocalReference<jobject>(MakeObjPtr(h_path_class_loader.Get())));
return soa.Env()->NewGlobalRef(local_ref.get());
}
#include "indirect_reference_table.h"
+#include "base/dumpable.h"
#include "gc_root-inl.h"
+#include "obj_ptr-inl.h"
#include "runtime-inl.h"
#include "verify_object-inl.h"
}
template<ReadBarrierOption kReadBarrierOption>
-inline mirror::Object* IndirectReferenceTable::Get(IndirectRef iref) const {
+inline ObjPtr<mirror::Object> IndirectReferenceTable::Get(IndirectRef iref) const {
if (!GetChecked(iref)) {
return nullptr;
}
uint32_t idx = ExtractIndex(iref);
- mirror::Object* obj = table_[idx].GetReference()->Read<kReadBarrierOption>();
- VerifyObject(obj);
+ ObjPtr<mirror::Object> obj = table_[idx].GetReference()->Read<kReadBarrierOption>();
+ VerifyObject(obj.Ptr());
return obj;
}
-inline void IndirectReferenceTable::Update(IndirectRef iref, mirror::Object* obj) {
+inline void IndirectReferenceTable::Update(IndirectRef iref, ObjPtr<mirror::Object> obj) {
if (!GetChecked(iref)) {
LOG(WARNING) << "IndirectReferenceTable Update failed to find reference " << iref;
return;
table_[idx].SetReference(obj);
}
+inline void IrtEntry::Add(ObjPtr<mirror::Object> obj) {
+ ++serial_;
+ if (serial_ == kIRTPrevCount) {
+ serial_ = 0;
+ }
+ references_[serial_] = GcRoot<mirror::Object>(obj);
+}
+
+inline void IrtEntry::SetReference(ObjPtr<mirror::Object> obj) {
+ DCHECK_LT(serial_, kIRTPrevCount);
+ references_[serial_] = GcRoot<mirror::Object>(obj);
+}
+
} // namespace art
#endif // ART_RUNTIME_INDIRECT_REFERENCE_TABLE_INL_H_
#include "indirect_reference_table-inl.h"
+#include "base/dumpable-inl.h"
#include "base/systrace.h"
#include "jni_internal.h"
#include "nth_caller_visitor.h"
return "IndirectRefKind Error";
}
-template<typename T>
-class MutatorLockedDumpable {
- public:
- explicit MutatorLockedDumpable(T& value)
- REQUIRES_SHARED(Locks::mutator_lock_) : value_(value) {
- }
-
- void Dump(std::ostream& os) const REQUIRES_SHARED(Locks::mutator_lock_) {
- value_.Dump(os);
- }
-
- private:
- T& value_;
-
- DISALLOW_COPY_AND_ASSIGN(MutatorLockedDumpable);
-};
-
-template<typename T>
-std::ostream& operator<<(std::ostream& os, const MutatorLockedDumpable<T>& rhs)
-// TODO: should be REQUIRES_SHARED(Locks::mutator_lock_) however annotalysis
-// currently fails for this.
- NO_THREAD_SAFETY_ANALYSIS {
- rhs.Dump(os);
- return os;
-}
-
void IndirectReferenceTable::AbortIfNoCheckJNI(const std::string& msg) {
// If -Xcheck:jni is on, it'll give a more detailed error before aborting.
JavaVMExt* vm = Runtime::Current()->GetJavaVM();
return table_mem_map_.get() != nullptr;
}
-IndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) {
+IndirectRef IndirectReferenceTable::Add(uint32_t cookie, ObjPtr<mirror::Object> obj) {
IRTSegmentState prevState;
prevState.all = cookie;
size_t topIndex = segment_state_.parts.topIndex;
CHECK(obj != nullptr);
- VerifyObject(obj);
+ VerifyObject(obj.Ptr());
DCHECK(table_ != nullptr);
DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles);
void IndirectReferenceTable::AssertEmpty() {
for (size_t i = 0; i < Capacity(); ++i) {
if (!table_[i].GetReference()->IsNull()) {
- ScopedObjectAccess soa(Thread::Current());
LOG(FATAL) << "Internal Error: non-empty local reference table\n"
<< MutatorLockedDumpable<IndirectReferenceTable>(*this);
+ UNREACHABLE();
}
}
}
os << kind_ << " table dump:\n";
ReferenceTable::Table entries;
for (size_t i = 0; i < Capacity(); ++i) {
- mirror::Object* obj = table_[i].GetReference()->Read<kWithoutReadBarrier>();
+ ObjPtr<mirror::Object> obj = table_[i].GetReference()->Read<kWithoutReadBarrier>();
if (obj != nullptr) {
obj = table_[i].GetReference()->Read();
entries.push_back(GcRoot<mirror::Object>(obj));
#include "base/logging.h"
#include "base/mutex.h"
#include "gc_root.h"
+#include "obj_ptr.h"
#include "object_callbacks.h"
#include "offsets.h"
#include "read_barrier_option.h"
static const size_t kIRTPrevCount = kIsDebugBuild ? 7 : 3;
class IrtEntry {
public:
- void Add(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
- ++serial_;
- if (serial_ == kIRTPrevCount) {
- serial_ = 0;
- }
- references_[serial_] = GcRoot<mirror::Object>(obj);
- }
+ void Add(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_);
+
GcRoot<mirror::Object>* GetReference() {
DCHECK_LT(serial_, kIRTPrevCount);
return &references_[serial_];
}
+
uint32_t GetSerial() const {
return serial_;
}
- void SetReference(mirror::Object* obj) {
- DCHECK_LT(serial_, kIRTPrevCount);
- references_[serial_] = GcRoot<mirror::Object>(obj);
- }
+
+ void SetReference(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_);
private:
uint32_t serial_;
return *this;
}
- GcRoot<mirror::Object>* operator*() {
+ GcRoot<mirror::Object>* operator*() REQUIRES_SHARED(Locks::mutator_lock_) {
// This does not have a read barrier as this is used to visit roots.
return table_[i_].GetReference();
}
* Returns nullptr if the table is full (max entries reached, or alloc
* failed during expansion).
*/
- IndirectRef Add(uint32_t cookie, mirror::Object* obj)
+ IndirectRef Add(uint32_t cookie, ObjPtr<mirror::Object> obj)
REQUIRES_SHARED(Locks::mutator_lock_);
/*
* Returns kInvalidIndirectRefObject if iref is invalid.
*/
template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- mirror::Object* Get(IndirectRef iref) const REQUIRES_SHARED(Locks::mutator_lock_)
+ ObjPtr<mirror::Object> Get(IndirectRef iref) const REQUIRES_SHARED(Locks::mutator_lock_)
ALWAYS_INLINE;
// Synchronized get which reads a reference, acquiring a lock if necessary.
template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
- mirror::Object* SynchronizedGet(IndirectRef iref) const REQUIRES_SHARED(Locks::mutator_lock_) {
+ ObjPtr<mirror::Object> SynchronizedGet(IndirectRef iref) const
+ REQUIRES_SHARED(Locks::mutator_lock_) {
return Get<kReadBarrierOption>(iref);
}
*
* Updates an existing indirect reference to point to a new object.
*/
- void Update(IndirectRef iref, mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+ void Update(IndirectRef iref, ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_);
/*
* Remove an existing entry.
*/
bool Remove(uint32_t cookie, IndirectRef iref);
- void AssertEmpty();
+ void AssertEmpty() REQUIRES_SHARED(Locks::mutator_lock_);
void Dump(std::ostream& os) const REQUIRES_SHARED(Locks::mutator_lock_);
static void AbortIfNoCheckJNI(const std::string& msg);
/* extra debugging checks */
- bool GetChecked(IndirectRef) const;
+ bool GetChecked(IndirectRef) const REQUIRES_SHARED(Locks::mutator_lock_);
bool CheckEntry(const char*, IndirectRef, int) const;
/* semi-public - read/write by jni down calls */
EXPECT_TRUE(iref2 != nullptr);
CheckDump(&irt, 3, 3);
- EXPECT_EQ(obj0, irt.Get(iref0));
- EXPECT_EQ(obj1, irt.Get(iref1));
- EXPECT_EQ(obj2, irt.Get(iref2));
+ EXPECT_OBJ_PTR_EQ(obj0, irt.Get(iref0));
+ EXPECT_OBJ_PTR_EQ(obj1, irt.Get(iref1));
+ EXPECT_OBJ_PTR_EQ(obj2, irt.Get(iref2));
EXPECT_TRUE(irt.Remove(cookie, iref0));
CheckDump(&irt, 2, 2);
JNIEnvExt* env = self->GetJniEnv();
ScopedObjectAccessUnchecked soa(self);
- mirror::Object* java_method_obj = shadow_frame->GetVRegReference(arg_offset);
+ ObjPtr<mirror::Object> java_method_obj = shadow_frame->GetVRegReference(arg_offset);
ScopedLocalRef<jobject> java_method(env,
java_method_obj == nullptr ? nullptr :env->AddLocalReference<jobject>(java_method_obj));
- mirror::Object* java_receiver_obj = shadow_frame->GetVRegReference(arg_offset + 1);
+ ObjPtr<mirror::Object> java_receiver_obj = shadow_frame->GetVRegReference(arg_offset + 1);
ScopedLocalRef<jobject> java_receiver(env,
java_receiver_obj == nullptr ? nullptr : env->AddLocalReference<jobject>(java_receiver_obj));
- mirror::Object* java_args_obj = shadow_frame->GetVRegReference(arg_offset + 2);
+ ObjPtr<mirror::Object> java_args_obj = shadow_frame->GetVRegReference(arg_offset + 2);
ScopedLocalRef<jobject> java_args(env,
java_args_obj == nullptr ? nullptr : env->AddLocalReference<jobject>(java_args_obj));
}
mirror::Object* JavaVMExt::DecodeGlobal(IndirectRef ref) {
- return globals_.SynchronizedGet(ref);
+ return globals_.SynchronizedGet(ref).Ptr();
}
void JavaVMExt::UpdateGlobal(Thread* self, IndirectRef ref, mirror::Object* result) {
// if MayAccessWeakGlobals is false.
DCHECK_EQ(GetIndirectRefKind(ref), kWeakGlobal);
if (LIKELY(MayAccessWeakGlobalsUnlocked(self))) {
- return weak_globals_.SynchronizedGet(ref);
+ return weak_globals_.SynchronizedGet(ref).Ptr();
}
MutexLock mu(self, weak_globals_lock_);
return DecodeWeakGlobalLocked(self, ref);
while (UNLIKELY(!MayAccessWeakGlobals(self))) {
weak_globals_add_condition_.WaitHoldingLocks(self);
}
- return weak_globals_.Get(ref);
+ return weak_globals_.Get(ref).Ptr();
}
mirror::Object* JavaVMExt::DecodeWeakGlobalDuringShutdown(Thread* self, IndirectRef ref) {
if (!kUseReadBarrier) {
DCHECK(allow_accessing_weak_globals_.LoadSequentiallyConsistent());
}
- return weak_globals_.SynchronizedGet(ref);
+ return weak_globals_.SynchronizedGet(ref).Ptr();
}
bool JavaVMExt::IsWeakGlobalCleared(Thread* self, IndirectRef ref) {
#include "jni_env_ext.h"
+#include "indirect_reference_table-inl.h"
+#include "obj_ptr-inl.h"
#include "utils.h"
namespace art {
template<typename T>
-inline T JNIEnvExt::AddLocalReference(mirror::Object* obj) {
+inline T JNIEnvExt::AddLocalReference(ObjPtr<mirror::Object> obj) {
IndirectRef ref = locals.Add(local_ref_cookie, obj);
// TODO: fix this to understand PushLocalFrame, so we can turn it on.
void PopFrame() REQUIRES_SHARED(Locks::mutator_lock_);
template<typename T>
- T AddLocalReference(mirror::Object* obj)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ T AddLocalReference(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_);
static Offset SegmentStateOffset(size_t pointer_size);
static Offset LocalRefCookieOffset(size_t pointer_size);
#include "art_method.h"
#include "class_linker.h"
+#include "obj_ptr-inl.h"
#include "read_barrier-inl.h"
namespace art {
-inline bool Runtime::IsClearedJniWeakGlobal(mirror::Object* obj) {
+inline bool Runtime::IsClearedJniWeakGlobal(ObjPtr<mirror::Object> obj) {
return obj == GetClearedJniWeakGlobal();
}
#include "instrumentation.h"
#include "jobject_comparator.h"
#include "method_reference.h"
+#include "obj_ptr.h"
#include "object_callbacks.h"
#include "offsets.h"
#include "process_state.h"
}
// Is the given object the special object used to mark a cleared JNI weak global?
- bool IsClearedJniWeakGlobal(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsClearedJniWeakGlobal(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_);
// Get the special object used to mark a cleared JNI weak global.
mirror::Object* GetClearedJniWeakGlobal() REQUIRES_SHARED(Locks::mutator_lock_);
}
template<typename T>
-inline T ScopedObjectAccessAlreadyRunnable::AddLocalReference(mirror::Object* obj) const {
+inline T ScopedObjectAccessAlreadyRunnable::AddLocalReference(ObjPtr<mirror::Object> obj) const {
Locks::mutator_lock_->AssertSharedHeld(Self());
DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states.
DCHECK_NE(obj, Runtime::Current()->GetClearedJniWeakGlobal());
return obj == nullptr ? nullptr : Env()->AddLocalReference<T>(obj);
}
-template<typename T, typename MirrorType, bool kPoison>
-inline T ScopedObjectAccessAlreadyRunnable::AddLocalReference(
- ObjPtr<MirrorType, kPoison> obj) const {
- return AddLocalReference<T>(obj.Ptr());
-}
-
template<typename T, bool kPoison>
inline ObjPtr<T, kPoison> ScopedObjectAccessAlreadyRunnable::Decode(jobject obj) const {
Locks::mutator_lock_->AssertSharedHeld(Self());
* This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
* it's best if we don't grab a mutex.
*/
- template<typename T, typename MirrorType, bool kPoison = kIsDebugBuild>
- T AddLocalReference(ObjPtr<MirrorType, kPoison> obj) const
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- // TODO: Delete
template<typename T>
- T AddLocalReference(mirror::Object* obj) const
+ T AddLocalReference(ObjPtr<mirror::Object> obj) const
REQUIRES_SHARED(Locks::mutator_lock_);
template<typename T, bool kPoison = kIsDebugBuild>
}
IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
IndirectRefKind kind = GetIndirectRefKind(ref);
- mirror::Object* result;
+ ObjPtr<mirror::Object> result;
bool expect_null = false;
// The "kinds" below are sorted by the frequency we expect to encounter them.
if (kind == kLocal) {
if (LIKELY(HandleScopeContains(obj))) {
// Read from handle scope.
result = reinterpret_cast<StackReference<mirror::Object>*>(obj)->AsMirrorPtr();
- VerifyObject(result);
+ VerifyObject(result.Ptr());
} else {
tlsPtr_.jni_env->vm->JniAbortF(nullptr, "use of invalid jobject %p", obj);
expect_null = true;
tlsPtr_.jni_env->vm->JniAbortF(nullptr, "use of deleted %s %p",
ToStr<IndirectRefKind>(kind).c_str(), obj);
}
- return result;
+ return result.Ptr();
}
bool Thread::IsJWeakCleared(jweak obj) const {