object.cc revision a4962aaa16a401da6f9db3ef26209b4ba6e99045
1/*
2 * Copyright (C) 2011 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 <ctime>
18
19#include "object.h"
20
21#include "art_field.h"
22#include "art_field-inl.h"
23#include "array-inl.h"
24#include "class.h"
25#include "class-inl.h"
26#include "class_linker-inl.h"
27#include "field_helper.h"
28#include "gc/accounting/card_table-inl.h"
29#include "gc/heap.h"
30#include "iftable-inl.h"
31#include "monitor.h"
32#include "object-inl.h"
33#include "object_array-inl.h"
34#include "runtime.h"
35#include "handle_scope-inl.h"
36#include "throwable.h"
37#include "well_known_classes.h"
38
39namespace art {
40namespace mirror {
41
42class CopyReferenceFieldsWithReadBarrierVisitor {
43 public:
44  explicit CopyReferenceFieldsWithReadBarrierVisitor(Object* dest_obj)
45      : dest_obj_(dest_obj) {}
46
47  void operator()(Object* obj, MemberOffset offset, bool /* is_static */) const
48      ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
49    // GetFieldObject() contains a RB.
50    Object* ref = obj->GetFieldObject<Object>(offset);
51    // No WB here as a large object space does not have a card table
52    // coverage. Instead, cards will be marked separately.
53    dest_obj_->SetFieldObjectWithoutWriteBarrier<false, false>(offset, ref);
54  }
55
56  void operator()(mirror::Class* klass, mirror::Reference* ref) const
57      ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
58    // Copy java.lang.ref.Reference.referent which isn't visited in
59    // Object::VisitReferences().
60    DCHECK(klass->IsTypeOfReferenceClass());
61    this->operator()(ref, mirror::Reference::ReferentOffset(), false);
62  }
63
64 private:
65  Object* const dest_obj_;
66};
67
68Object* Object::CopyObject(Thread* self, mirror::Object* dest, mirror::Object* src,
69                           size_t num_bytes) {
70  // Copy instance data.  We assume memcpy copies by words.
71  // TODO: expose and use move32.
72  byte* src_bytes = reinterpret_cast<byte*>(src);
73  byte* dst_bytes = reinterpret_cast<byte*>(dest);
74  size_t offset = sizeof(Object);
75  memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
76  if (kUseBakerOrBrooksReadBarrier) {
77    // We need a RB here. After the memcpy that covers the whole
78    // object above, copy references fields one by one again with a
79    // RB. TODO: Optimize this later?
80    CopyReferenceFieldsWithReadBarrierVisitor visitor(dest);
81    src->VisitReferences<true>(visitor, visitor);
82  }
83  gc::Heap* heap = Runtime::Current()->GetHeap();
84  // Perform write barriers on copied object references.
85  Class* c = src->GetClass();
86  if (c->IsArrayClass()) {
87    if (!c->GetComponentType()->IsPrimitive()) {
88      ObjectArray<Object>* array = dest->AsObjectArray<Object>();
89      heap->WriteBarrierArray(dest, 0, array->GetLength());
90    }
91  } else {
92    heap->WriteBarrierEveryFieldOf(dest);
93  }
94  if (c->IsFinalizable()) {
95    heap->AddFinalizerReference(self, &dest);
96  }
97  return dest;
98}
99
100// An allocation pre-fence visitor that copies the object.
101class CopyObjectVisitor {
102 public:
103  explicit CopyObjectVisitor(Thread* self, Handle<Object>* orig, size_t num_bytes)
104      : self_(self), orig_(orig), num_bytes_(num_bytes) {
105  }
106
107  void operator()(Object* obj, size_t usable_size) const
108      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
109    UNUSED(usable_size);
110    Object::CopyObject(self_, obj, orig_->Get(), num_bytes_);
111  }
112
113 private:
114  Thread* const self_;
115  Handle<Object>* const orig_;
116  const size_t num_bytes_;
117  DISALLOW_COPY_AND_ASSIGN(CopyObjectVisitor);
118};
119
120Object* Object::Clone(Thread* self) {
121  CHECK(!IsClass()) << "Can't clone classes.";
122  // Object::SizeOf gets the right size even if we're an array. Using c->AllocObject() here would
123  // be wrong.
124  gc::Heap* heap = Runtime::Current()->GetHeap();
125  size_t num_bytes = SizeOf();
126  StackHandleScope<1> hs(self);
127  Handle<Object> this_object(hs.NewHandle(this));
128  Object* copy;
129  CopyObjectVisitor visitor(self, &this_object, num_bytes);
130  if (heap->IsMovableObject(this)) {
131    copy = heap->AllocObject<true>(self, GetClass(), num_bytes, visitor);
132  } else {
133    copy = heap->AllocNonMovableObject<true>(self, GetClass(), num_bytes, visitor);
134  }
135  return copy;
136}
137
138int32_t Object::GenerateIdentityHashCode() {
139  static AtomicInteger seed(987654321 + std::time(nullptr));
140  int32_t expected_value, new_value;
141  do {
142    expected_value = static_cast<uint32_t>(seed.LoadRelaxed());
143    new_value = expected_value * 1103515245 + 12345;
144  } while ((expected_value & LockWord::kHashMask) == 0 ||
145      !seed.CompareExchangeWeakRelaxed(expected_value, new_value));
146  return expected_value & LockWord::kHashMask;
147}
148
149int32_t Object::IdentityHashCode() const {
150  mirror::Object* current_this = const_cast<mirror::Object*>(this);
151  while (true) {
152    LockWord lw = current_this->GetLockWord(false);
153    switch (lw.GetState()) {
154      case LockWord::kUnlocked: {
155        // Try to compare and swap in a new hash, if we succeed we will return the hash on the next
156        // loop iteration.
157        LockWord hash_word(LockWord::FromHashCode(GenerateIdentityHashCode()));
158        DCHECK_EQ(hash_word.GetState(), LockWord::kHashCode);
159        if (const_cast<Object*>(this)->CasLockWordWeakRelaxed(lw, hash_word)) {
160          return hash_word.GetHashCode();
161        }
162        break;
163      }
164      case LockWord::kThinLocked: {
165        // Inflate the thin lock to a monitor and stick the hash code inside of the monitor. May
166        // fail spuriously.
167        Thread* self = Thread::Current();
168        StackHandleScope<1> hs(self);
169        Handle<mirror::Object> h_this(hs.NewHandle(current_this));
170        Monitor::InflateThinLocked(self, h_this, lw, GenerateIdentityHashCode());
171        // A GC may have occurred when we switched to kBlocked.
172        current_this = h_this.Get();
173        break;
174      }
175      case LockWord::kFatLocked: {
176        // Already inflated, return the has stored in the monitor.
177        Monitor* monitor = lw.FatLockMonitor();
178        DCHECK(monitor != nullptr);
179        return monitor->GetHashCode();
180      }
181      case LockWord::kHashCode: {
182        return lw.GetHashCode();
183      }
184      default: {
185        LOG(FATAL) << "Invalid state during hashcode " << lw.GetState();
186        break;
187      }
188    }
189  }
190  LOG(FATAL) << "Unreachable";
191  return 0;
192}
193
194void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, Object* new_value) {
195  Class* c = GetClass();
196  Runtime* runtime = Runtime::Current();
197  if (runtime->GetClassLinker() == nullptr || !runtime->IsStarted() ||
198      !runtime->GetHeap()->IsObjectValidationEnabled() || !c->IsResolved()) {
199    return;
200  }
201  for (Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
202    ObjectArray<ArtField>* fields = cur->GetIFields();
203    if (fields != NULL) {
204      size_t num_ref_ifields = cur->NumReferenceInstanceFields();
205      for (size_t i = 0; i < num_ref_ifields; ++i) {
206        ArtField* field = fields->Get(i);
207        if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
208          StackHandleScope<1> hs(Thread::Current());
209          FieldHelper fh(hs.NewHandle(field));
210          CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
211          return;
212        }
213      }
214    }
215  }
216  if (c->IsArrayClass()) {
217    // Bounds and assign-ability done in the array setter.
218    return;
219  }
220  if (IsClass()) {
221    ObjectArray<ArtField>* fields = AsClass()->GetSFields();
222    if (fields != NULL) {
223      size_t num_ref_sfields = AsClass()->NumReferenceStaticFields();
224      for (size_t i = 0; i < num_ref_sfields; ++i) {
225        ArtField* field = fields->Get(i);
226        if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
227          StackHandleScope<1> hs(Thread::Current());
228          FieldHelper fh(hs.NewHandle(field));
229          CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
230          return;
231        }
232      }
233    }
234  }
235  LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this)
236      << " of type " << PrettyDescriptor(c) << " at offset " << field_offset;
237}
238
239}  // namespace mirror
240}  // namespace art
241