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 */
23static 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 */
54static 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 */
70static 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 */
83static 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 */
111static 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 */
130static 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 */
143static 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 */
157static 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