Home | History | Annotate | Download | only in mirror
      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 "object.h"
     18 
     19 #include "art_field.h"
     20 #include "art_field-inl.h"
     21 #include "array-inl.h"
     22 #include "class.h"
     23 #include "class-inl.h"
     24 #include "class_linker-inl.h"
     25 #include "gc/accounting/card_table-inl.h"
     26 #include "gc/heap.h"
     27 #include "iftable-inl.h"
     28 #include "monitor.h"
     29 #include "object-inl.h"
     30 #include "object_array-inl.h"
     31 #include "object_utils.h"
     32 #include "runtime.h"
     33 #include "sirt_ref.h"
     34 #include "throwable.h"
     35 #include "well_known_classes.h"
     36 
     37 namespace art {
     38 namespace mirror {
     39 
     40 Object* Object::Clone(Thread* self) {
     41   Class* c = GetClass();
     42   DCHECK(!c->IsClassClass());
     43 
     44   // Object::SizeOf gets the right size even if we're an array.
     45   // Using c->AllocObject() here would be wrong.
     46   size_t num_bytes = SizeOf();
     47   gc::Heap* heap = Runtime::Current()->GetHeap();
     48   SirtRef<Object> copy(self, heap->AllocObject(self, c, num_bytes));
     49   if (copy.get() == NULL) {
     50     return NULL;
     51   }
     52 
     53   // Copy instance data.  We assume memcpy copies by words.
     54   // TODO: expose and use move32.
     55   byte* src_bytes = reinterpret_cast<byte*>(this);
     56   byte* dst_bytes = reinterpret_cast<byte*>(copy.get());
     57   size_t offset = sizeof(Object);
     58   memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
     59 
     60   // Perform write barriers on copied object references.
     61   if (c->IsArrayClass()) {
     62     if (!c->GetComponentType()->IsPrimitive()) {
     63       const ObjectArray<Object>* array = copy->AsObjectArray<Object>();
     64       heap->WriteBarrierArray(copy.get(), 0, array->GetLength());
     65     }
     66   } else {
     67     for (const Class* klass = c; klass != NULL; klass = klass->GetSuperClass()) {
     68       size_t num_reference_fields = klass->NumReferenceInstanceFields();
     69       for (size_t i = 0; i < num_reference_fields; ++i) {
     70         ArtField* field = klass->GetInstanceField(i);
     71         MemberOffset field_offset = field->GetOffset();
     72         const Object* ref = copy->GetFieldObject<const Object*>(field_offset, false);
     73         heap->WriteBarrierField(copy.get(), field_offset, ref);
     74       }
     75     }
     76   }
     77 
     78   if (c->IsFinalizable()) {
     79     heap->AddFinalizerReference(Thread::Current(), copy.get());
     80   }
     81 
     82   return copy.get();
     83 }
     84 
     85 void Object::CheckFieldAssignmentImpl(MemberOffset field_offset, const Object* new_value) {
     86   const Class* c = GetClass();
     87   if (Runtime::Current()->GetClassLinker() == NULL ||
     88       !Runtime::Current()->GetHeap()->IsObjectValidationEnabled() ||
     89       !c->IsResolved()) {
     90     return;
     91   }
     92   for (const Class* cur = c; cur != NULL; cur = cur->GetSuperClass()) {
     93     ObjectArray<ArtField>* fields = cur->GetIFields();
     94     if (fields != NULL) {
     95       size_t num_ref_ifields = cur->NumReferenceInstanceFields();
     96       for (size_t i = 0; i < num_ref_ifields; ++i) {
     97         ArtField* field = fields->Get(i);
     98         if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
     99           FieldHelper fh(field);
    100           CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
    101           return;
    102         }
    103       }
    104     }
    105   }
    106   if (c->IsArrayClass()) {
    107     // Bounds and assign-ability done in the array setter.
    108     return;
    109   }
    110   if (IsClass()) {
    111     ObjectArray<ArtField>* fields = AsClass()->GetSFields();
    112     if (fields != NULL) {
    113       size_t num_ref_sfields = AsClass()->NumReferenceStaticFields();
    114       for (size_t i = 0; i < num_ref_sfields; ++i) {
    115         ArtField* field = fields->Get(i);
    116         if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
    117           FieldHelper fh(field);
    118           CHECK(fh.GetType()->IsAssignableFrom(new_value->GetClass()));
    119           return;
    120         }
    121       }
    122     }
    123   }
    124   LOG(FATAL) << "Failed to find field for assignment to " << reinterpret_cast<void*>(this)
    125       << " of type " << PrettyDescriptor(c) << " at offset " << field_offset;
    126 }
    127 
    128 }  // namespace mirror
    129 }  // namespace art
    130