Home | History | Annotate | Download | only in alloc
      1 /*
      2  * Copyright (C) 2010 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 DALVIK_ALLOC_VISITINLINES_H_
     18 #define DALVIK_ALLOC_VISITINLINES_H_
     19 
     20 /*
     21  * Visits the instance fields of a class or data object.
     22  */
     23 static void visitFields(Visitor *visitor, Object *obj, void *arg)
     24 {
     25     assert(visitor != NULL);
     26     assert(obj != NULL);
     27     assert(obj->clazz != NULL);
     28     if (obj->clazz->refOffsets != CLASS_WALK_SUPER) {
     29         size_t refOffsets = obj->clazz->refOffsets;
     30         while (refOffsets != 0) {
     31             size_t rshift = CLZ(refOffsets);
     32             size_t offset = CLASS_OFFSET_FROM_CLZ(rshift);
     33             Object **ref = (Object **)BYTE_OFFSET(obj, offset);
     34             (*visitor)(ref, arg);
     35             refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
     36         }
     37     } else {
     38         for (ClassObject *clazz = obj->clazz;
     39              clazz != NULL;
     40              clazz = clazz->super) {
     41             InstField *field = clazz->ifields;
     42             for (int i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
     43                 size_t offset = field->byteOffset;
     44                 Object **ref = (Object **)BYTE_OFFSET(obj, offset);
     45                 (*visitor)(ref, arg);
     46             }
     47         }
     48     }
     49 }
     50 
     51 /*
     52  * Visits the static fields of a class object.
     53  */
     54 static void visitStaticFields(Visitor *visitor, ClassObject *clazz,
     55                               void *arg)
     56 {
     57     assert(visitor != NULL);
     58     assert(clazz != NULL);
     59     for (int i = 0; i < clazz->sfieldCount; ++i) {
     60         char ch = clazz->sfields[i].signature[0];
     61         if (ch == '[' || ch == 'L') {
     62             (*visitor)(&clazz->sfields[i].value.l, arg);
     63         }
     64     }
     65 }
     66 
     67 /*
     68  * Visit the interfaces of a class object.
     69  */
     70 static void visitInterfaces(Visitor *visitor, ClassObject *clazz,
     71                             void *arg)
     72 {
     73     assert(visitor != NULL);
     74     assert(clazz != NULL);
     75     for (int i = 0; i < clazz->interfaceCount; ++i) {
     76         (*visitor)(&clazz->interfaces[i], arg);
     77     }
     78 }
     79 
     80 /*
     81  * Visits all the references stored in a class object instance.
     82  */
     83 static void visitClassObject(Visitor *visitor, Object *obj, void *arg)
     84 {
     85     ClassObject *asClass;
     86 
     87     assert(visitor != NULL);
     88     assert(obj != NULL);
     89     assert(obj->clazz != NULL);
     90     assert(!strcmp(obj->clazz->descriptor, "Ljava/lang/Class;"));
     91     (*visitor)(&obj->clazz, arg);
     92     asClass = (ClassObject *)obj;
     93     if (IS_CLASS_FLAG_SET(asClass, CLASS_ISARRAY)) {
     94         (*visitor)(&asClass->elementClass, arg);
     95     }
     96     if (asClass->status > CLASS_IDX) {
     97         (*visitor)(&asClass->super, arg);
     98     }
     99     (*visitor)(&asClass->classLoader, arg);
    100     visitFields(visitor, obj, arg);
    101     visitStaticFields(visitor, asClass, arg);
    102     if (asClass->status > CLASS_IDX) {
    103       visitInterfaces(visitor, asClass, arg);
    104     }
    105 }
    106 
    107 /*
    108  * Visits the class object and, if the array is typed as an object
    109  * array, all of the array elements.
    110  */
    111 static void visitArrayObject(Visitor *visitor, Object *obj, void *arg)
    112 {
    113     assert(visitor != NULL);
    114     assert(obj != NULL);
    115     assert(obj->clazz != NULL);
    116     (*visitor)(&obj->clazz, arg);
    117     if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY)) {
    118         ArrayObject *array = (ArrayObject *)obj;
    119         Object **contents = (Object **)(void *)array->contents;
    120         for (size_t i = 0; i < array->length; ++i) {
    121             (*visitor)(&contents[i], arg);
    122         }
    123     }
    124 }
    125 
    126 /*
    127  * Visits the class object and reference typed instance fields of a
    128  * data object.
    129  */
    130 static void visitDataObject(Visitor *visitor, Object *obj, void *arg)
    131 {
    132     assert(visitor != NULL);
    133     assert(obj != NULL);
    134     assert(obj->clazz != NULL);
    135     (*visitor)(&obj->clazz, arg);
    136     visitFields(visitor, obj, arg);
    137 }
    138 
    139 /*
    140  * Like visitDataObject, but visits the hidden referent field that
    141  * belongings to the subclasses of java.lang.Reference.
    142  */
    143 static void visitReferenceObject(Visitor *visitor, Object *obj, void *arg)
    144 {
    145     assert(visitor != NULL);
    146     assert(obj != NULL);
    147     assert(obj->clazz != NULL);
    148     visitDataObject(visitor, obj, arg);
    149     size_t offset = gDvm.offJavaLangRefReference_referent;
    150     Object **ref = (Object **)BYTE_OFFSET(obj, offset);
    151     (*visitor)(ref, arg);
    152 }
    153 
    154 /*
    155  * Visits all of the reference stored in an object.
    156  */
    157 static void visitObject(Visitor *visitor, Object *obj, void *arg)
    158 {
    159     assert(visitor != NULL);
    160     assert(obj != NULL);
    161     assert(obj->clazz != NULL);
    162     if (dvmIsClassObject(obj)) {
    163         visitClassObject(visitor, obj, arg);
    164     } else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
    165         visitArrayObject(visitor, obj, arg);
    166     } else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISREFERENCE)) {
    167         visitReferenceObject(visitor, obj, arg);
    168     } else {
    169         visitDataObject(visitor, obj, arg);
    170     }
    171 }
    172 
    173 #endif  // DALVIK_ALLOC_VISITINLINES_H_
    174