• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_INDIRECT_REFERENCE_TABLE_INL_H_
18 #define ART_RUNTIME_INDIRECT_REFERENCE_TABLE_INL_H_
19 
20 #include "indirect_reference_table.h"
21 
22 #include "gc_root-inl.h"
23 #include "runtime-inl.h"
24 #include "verify_object-inl.h"
25 
26 namespace art {
27 namespace mirror {
28 class Object;
29 }  // namespace mirror
30 
31 // Verifies that the indirect table lookup is valid.
32 // Returns "false" if something looks bad.
GetChecked(IndirectRef iref)33 inline bool IndirectReferenceTable::GetChecked(IndirectRef iref) const {
34   if (UNLIKELY(iref == nullptr)) {
35     LOG(WARNING) << "Attempt to look up nullptr " << kind_;
36     return false;
37   }
38   if (UNLIKELY(GetIndirectRefKind(iref) == kHandleScopeOrInvalid)) {
39     AbortIfNoCheckJNI(StringPrintf("JNI ERROR (app bug): invalid %s %p",
40                                    GetIndirectRefKindString(kind_),
41                                    iref));
42     return false;
43   }
44   const int topIndex = segment_state_.parts.topIndex;
45   int idx = ExtractIndex(iref);
46   if (UNLIKELY(idx >= topIndex)) {
47     std::string msg = StringPrintf(
48         "JNI ERROR (app bug): accessed stale %s %p  (index %d in a table of size %d)",
49         GetIndirectRefKindString(kind_),
50         iref,
51         idx,
52         topIndex);
53     AbortIfNoCheckJNI(msg);
54     return false;
55   }
56   if (UNLIKELY(table_[idx].GetReference()->IsNull())) {
57     AbortIfNoCheckJNI(StringPrintf("JNI ERROR (app bug): accessed deleted %s %p",
58                                    GetIndirectRefKindString(kind_),
59                                    iref));
60     return false;
61   }
62   if (UNLIKELY(!CheckEntry("use", iref, idx))) {
63     return false;
64   }
65   return true;
66 }
67 
68 // Make sure that the entry at "idx" is correctly paired with "iref".
CheckEntry(const char * what,IndirectRef iref,int idx)69 inline bool IndirectReferenceTable::CheckEntry(const char* what, IndirectRef iref, int idx) const {
70   IndirectRef checkRef = ToIndirectRef(idx);
71   if (UNLIKELY(checkRef != iref)) {
72     std::string msg = StringPrintf(
73         "JNI ERROR (app bug): attempt to %s stale %s %p (should be %p)",
74         what,
75         GetIndirectRefKindString(kind_),
76         iref,
77         checkRef);
78     AbortIfNoCheckJNI(msg);
79     return false;
80   }
81   return true;
82 }
83 
84 template<ReadBarrierOption kReadBarrierOption>
Get(IndirectRef iref)85 inline mirror::Object* IndirectReferenceTable::Get(IndirectRef iref) const {
86   if (!GetChecked(iref)) {
87     return nullptr;
88   }
89   uint32_t idx = ExtractIndex(iref);
90   mirror::Object* obj = table_[idx].GetReference()->Read<kReadBarrierOption>();
91   VerifyObject(obj);
92   return obj;
93 }
94 
Update(IndirectRef iref,mirror::Object * obj)95 inline void IndirectReferenceTable::Update(IndirectRef iref, mirror::Object* obj) {
96   if (!GetChecked(iref)) {
97     LOG(WARNING) << "IndirectReferenceTable Update failed to find reference " << iref;
98     return;
99   }
100   uint32_t idx = ExtractIndex(iref);
101   table_[idx].SetReference(obj);
102 }
103 
104 }  // namespace art
105 
106 #endif  // ART_RUNTIME_INDIRECT_REFERENCE_TABLE_INL_H_
107