1 /*
2 * Copyright (C) 2015 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 #include "field-inl.h"
18
19 #include "class-inl.h"
20 #include "dex_cache-inl.h"
21 #include "object-inl.h"
22 #include "object_array-inl.h"
23 #include "write_barrier.h"
24
25 namespace art {
26 namespace mirror {
27
VisitTarget(ReflectiveValueVisitor * v)28 void Field::VisitTarget(ReflectiveValueVisitor* v) {
29 HeapReflectiveSourceInfo hrsi(kSourceJavaLangReflectField, this);
30 ArtField* orig = GetArtField();
31 ArtField* new_value = v->VisitField(orig, hrsi);
32 if (orig != new_value) {
33 SetOffset<false>(new_value->GetOffset().Int32Value());
34 SetDeclaringClass<false>(new_value->GetDeclaringClass());
35 auto new_range =
36 IsStatic() ? GetDeclaringClass()->GetSFields() : GetDeclaringClass()->GetIFields();
37 auto position = std::find_if(
38 new_range.begin(), new_range.end(), [&](const auto& f) { return &f == new_value; });
39 DCHECK(position != new_range.end());
40 SetArtFieldIndex<false>(std::distance(new_range.begin(), position));
41 WriteBarrier::ForEveryFieldWrite(this);
42 }
43 DCHECK_EQ(new_value, GetArtField());
44 }
45
GetArtField()46 ArtField* Field::GetArtField() {
47 ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
48 if (IsStatic()) {
49 DCHECK_LT(GetArtFieldIndex(), declaring_class->NumStaticFields());
50 return declaring_class->GetStaticField(GetArtFieldIndex());
51 } else {
52 DCHECK_LT(GetArtFieldIndex(), declaring_class->NumInstanceFields());
53 return declaring_class->GetInstanceField(GetArtFieldIndex());
54 }
55 }
56
CreateFromArtField(Thread * self,ArtField * field,bool force_resolve)57 ObjPtr<mirror::Field> Field::CreateFromArtField(Thread* self,
58 ArtField* field,
59 bool force_resolve) {
60 StackHandleScope<2> hs(self);
61 // Try to resolve type before allocating since this is a thread suspension point.
62 Handle<mirror::Class> type = hs.NewHandle(field->ResolveType());
63
64 if (type == nullptr) {
65 DCHECK(self->IsExceptionPending());
66 if (force_resolve) {
67 return nullptr;
68 } else {
69 // Can't resolve, clear the exception if it isn't OOME and continue with a null type.
70 mirror::Throwable* exception = self->GetException();
71 if (exception->GetClass()->DescriptorEquals("Ljava/lang/OutOfMemoryError;")) {
72 return nullptr;
73 }
74 self->ClearException();
75 }
76 }
77 auto ret = hs.NewHandle(ObjPtr<Field>::DownCast(GetClassRoot<Field>()->AllocObject(self)));
78 if (UNLIKELY(ret == nullptr)) {
79 self->AssertPendingOOMException();
80 return nullptr;
81 }
82 // We're initializing a newly allocated object, so we do not need to record that under
83 // a transaction. If the transaction is aborted, the whole object shall be unreachable.
84 ret->SetType</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(type.Get());
85 ret->SetDeclaringClass</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
86 field->GetDeclaringClass());
87 ret->SetAccessFlags</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
88 field->GetAccessFlags());
89 auto iter_range = field->IsStatic() ? field->GetDeclaringClass()->GetSFields()
90 : field->GetDeclaringClass()->GetIFields();
91 auto position = std::find_if(
92 iter_range.begin(), iter_range.end(), [&](const auto& f) { return &f == field; });
93 DCHECK(position != iter_range.end());
94 ret->SetArtFieldIndex</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
95 std::distance(iter_range.begin(), position));
96 ret->SetOffset</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
97 field->GetOffset().Int32Value());
98 return ret.Get();
99 }
100
101 } // namespace mirror
102 } // namespace art
103