blob: 103b1f6764d4c8c37f64e14899d751da20a6d751 [file] [log] [blame]
Carl Shapiroadc346f2010-06-03 23:01:39 -07001/*
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#include "Dalvik.h"
18#include "alloc/clz.h"
19#include "alloc/Visit.h"
20
21/*
22 * Visits the instance fields of a class or data object.
23 */
24static void visitInstanceFields(Visitor *visitor, Object *obj)
25{
26 assert(visitor != NULL);
27 assert(obj != NULL);
28 assert(obj->clazz != NULL);
29 LOGV("Entering visitInstanceFields(visitor=%p,obj=%p)", visitor, obj);
30 if (obj->clazz->refOffsets != CLASS_WALK_SUPER) {
31 size_t refOffsets = obj->clazz->refOffsets;
32 while (refOffsets != 0) {
33 size_t rshift = CLZ(refOffsets);
34 size_t offset = CLASS_OFFSET_FROM_CLZ(rshift);
35 Object **ref = BYTE_OFFSET(obj, offset);
36 (*visitor)(ref);
37 refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
38 }
39 } else {
40 ClassObject *clazz;
41 for (clazz = obj->clazz; clazz != NULL; clazz = clazz->super) {
42 InstField *field = clazz->ifields;
43 int i;
44 for (i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
45 size_t offset = field->byteOffset;
46 Object **ref = BYTE_OFFSET(obj, offset);
47 (*visitor)(ref);
48 }
49 }
50 }
51 LOGV("Exiting visitInstanceFields(visitor=%p,obj=%p)", visitor, obj);
52}
53
54/*
55 * Visits the static fields of a class object.
56 */
57static void visitStaticFields(Visitor *visitor, ClassObject *clazz)
58{
59 int i;
60
61 assert(visitor != NULL);
62 assert(clazz != NULL);
63 for (i = 0; i < clazz->sfieldCount; ++i) {
64 char ch = clazz->sfields[i].field.signature[0];
65 if (ch == '[' || ch == 'L') {
66 (*visitor)(&clazz->sfields[i].value.l);
67 }
68 }
69}
70
71/*
72 * Visit the interfaces of a class object.
73 */
74static void visitInterfaces(Visitor *visitor, ClassObject *clazz)
75{
76 int i;
77
78 assert(visitor != NULL);
79 assert(clazz != NULL);
80 for (i = 0; i < clazz->interfaceCount; ++i) {
81 (*visitor)(&clazz->interfaces[i]);
82 }
83}
84
85/*
86 * Visits all the references stored in a class object instance.
87 */
88static void visitClassObject(Visitor *visitor, ClassObject *obj)
89{
90 assert(visitor != NULL);
91 assert(obj != NULL);
92 LOGV("Entering visitClassObject(visitor=%p,obj=%p)", visitor, obj);
Barry Hayesc49db852010-05-14 13:43:34 -070093 assert(!strcmp(obj->obj.clazz->descriptor, "Ljava/lang/Class;"));
Carl Shapiroadc346f2010-06-03 23:01:39 -070094 (*visitor)(&obj->obj.clazz);
95 if (IS_CLASS_FLAG_SET(obj, CLASS_ISARRAY)) {
96 (*visitor)(&obj->elementClass);
97 }
Barry Hayesc49db852010-05-14 13:43:34 -070098 if (obj->status > CLASS_IDX) {
99 (*visitor)(&obj->super);
100 }
Carl Shapiroadc346f2010-06-03 23:01:39 -0700101 (*visitor)(&obj->classLoader);
102 visitInstanceFields(visitor, (Object *)obj);
103 visitStaticFields(visitor, obj);
Barry Hayesc49db852010-05-14 13:43:34 -0700104 if (obj->status > CLASS_IDX) {
105 visitInterfaces(visitor, obj);
106 }
Carl Shapiroadc346f2010-06-03 23:01:39 -0700107 LOGV("Exiting visitClassObject(visitor=%p,obj=%p)", visitor, obj);
108}
109
110/*
111 * Visits the class object and, if the array is typed as an object
112 * array, all of the array elements.
113 */
114static void visitArrayObject(Visitor *visitor, Object *obj)
115{
116 assert(visitor != NULL);
117 assert(obj != NULL);
118 assert(obj->clazz != NULL);
119 LOGV("Entering visitArrayObject(visitor=%p,obj=%p)", visitor, obj);
120 (*visitor)(&obj->clazz);
121 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY)) {
122 ArrayObject *array = (ArrayObject *)obj;
123 Object **contents = (Object **)array->contents;
124 size_t i;
125 for (i = 0; i < array->length; ++i) {
126 (*visitor)(&contents[i]);
127 }
128 }
129 LOGV("Exiting visitArrayObject(visitor=%p,obj=%p)", visitor, obj);
130}
131
132/*
133 * Visits the class object and reference typed instance fields of a
134 * data object.
135 */
136static void visitDataObject(Visitor *visitor, Object *obj)
137{
138 assert(visitor != NULL);
139 assert(obj != NULL);
140 assert(obj->clazz != NULL);
141 LOGV("Entering visitDataObject(visitor=%p,obj=%p)", visitor, obj);
142 (*visitor)(&obj->clazz);
143 visitInstanceFields(visitor, obj);
144 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISREFERENCE)) {
145 size_t offset = gDvm.offJavaLangRefReference_referent;
146 Object **ref = BYTE_OFFSET(obj, offset);
147 (*visitor)(ref);
148 }
149 LOGV("Exiting visitDataObject(visitor=%p,obj=%p)", visitor, obj);
150}
151
152/*
153 * Visits all of the reference stored in an object.
154 */
155void dvmVisitObject(Visitor *visitor, Object *obj)
156{
157 assert(visitor != NULL);
158 assert(obj != NULL);
Barry Hayes899cdb72010-06-08 09:59:12 -0700159 assert(obj->clazz != NULL);
Carl Shapiroadc346f2010-06-03 23:01:39 -0700160 LOGV("Entering dvmVisitObject(visitor=%p,obj=%p)", visitor, obj);
Barry Hayesc49db852010-05-14 13:43:34 -0700161 if (obj->clazz == gDvm.classJavaLangClass) {
Carl Shapiroadc346f2010-06-03 23:01:39 -0700162 visitClassObject(visitor, (ClassObject *)obj);
Barry Hayes899cdb72010-06-08 09:59:12 -0700163 } else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
164 visitArrayObject(visitor, obj);
Carl Shapiroadc346f2010-06-03 23:01:39 -0700165 } else {
Barry Hayes899cdb72010-06-08 09:59:12 -0700166 visitDataObject(visitor, obj);
Carl Shapiroadc346f2010-06-03 23:01:39 -0700167 }
168 LOGV("Exiting dvmVisitObject(visitor=%p,obj=%p)", visitor, obj);
169}