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