blob: 959567e417c3954a0e70d823f9a38810381b4547 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _DALVIK_ALLOC_VISITINLINES
#define _DALVIK_ALLOC_VISITINLINES
/*
* Visits the instance fields of a class or data object.
*/
static void visitFields(Visitor *visitor, Object *obj, void *arg)
{
assert(visitor != NULL);
assert(obj != NULL);
assert(obj->clazz != NULL);
if (obj->clazz->refOffsets != CLASS_WALK_SUPER) {
size_t refOffsets = obj->clazz->refOffsets;
while (refOffsets != 0) {
size_t rshift = CLZ(refOffsets);
size_t offset = CLASS_OFFSET_FROM_CLZ(rshift);
Object **ref = BYTE_OFFSET(obj, offset);
(*visitor)(ref, arg);
refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
}
} else {
ClassObject *clazz;
for (clazz = obj->clazz; clazz != NULL; clazz = clazz->super) {
InstField *field = clazz->ifields;
int i;
for (i = 0; i < clazz->ifieldRefCount; ++i, ++field) {
size_t offset = field->byteOffset;
Object **ref = BYTE_OFFSET(obj, offset);
(*visitor)(ref, arg);
}
}
}
}
/*
* Visits the static fields of a class object.
*/
static void visitStaticFields(Visitor *visitor, ClassObject *clazz,
void *arg)
{
int i;
assert(visitor != NULL);
assert(clazz != NULL);
for (i = 0; i < clazz->sfieldCount; ++i) {
char ch = clazz->sfields[i].field.signature[0];
if (ch == '[' || ch == 'L') {
(*visitor)(&clazz->sfields[i].value.l, arg);
}
}
}
/*
* Visit the interfaces of a class object.
*/
static void visitInterfaces(Visitor *visitor, ClassObject *clazz,
void *arg)
{
int i;
assert(visitor != NULL);
assert(clazz != NULL);
for (i = 0; i < clazz->interfaceCount; ++i) {
(*visitor)(&clazz->interfaces[i], arg);
}
}
/*
* Visits all the references stored in a class object instance.
*/
static void visitClassObject(Visitor *visitor, Object *obj, void *arg)
{
ClassObject *asClass;
assert(visitor != NULL);
assert(obj != NULL);
assert(obj->clazz != NULL);
assert(!strcmp(obj->clazz->descriptor, "Ljava/lang/Class;"));
(*visitor)(&obj->clazz, arg);
asClass = (ClassObject *)obj;
if (IS_CLASS_FLAG_SET(asClass, CLASS_ISARRAY)) {
(*visitor)(&asClass->elementClass, arg);
}
if (asClass->status > CLASS_IDX) {
(*visitor)(&asClass->super, arg);
}
(*visitor)(&asClass->classLoader, arg);
visitFields(visitor, obj, arg);
visitStaticFields(visitor, asClass, arg);
if (asClass->status > CLASS_IDX) {
visitInterfaces(visitor, asClass, arg);
}
}
/*
* Visits the class object and, if the array is typed as an object
* array, all of the array elements.
*/
static void visitArrayObject(Visitor *visitor, Object *obj, void *arg)
{
assert(visitor != NULL);
assert(obj != NULL);
assert(obj->clazz != NULL);
(*visitor)(&obj->clazz, arg);
if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISOBJECTARRAY)) {
ArrayObject *array = (ArrayObject *)obj;
Object **contents = (Object **)array->contents;
size_t i;
for (i = 0; i < array->length; ++i) {
(*visitor)(&contents[i], arg);
}
}
}
/*
* Visits the class object and reference typed instance fields of a
* data object.
*/
static void visitDataObject(Visitor *visitor, Object *obj, void *arg)
{
assert(visitor != NULL);
assert(obj != NULL);
assert(obj->clazz != NULL);
(*visitor)(&obj->clazz, arg);
visitFields(visitor, obj, arg);
}
/*
* Like visitDataObject, but visits the hidden referent field that
* belongings to the subclasses of java.lang.Reference.
*/
static void visitReferenceObject(Visitor *visitor, Object *obj, void *arg)
{
assert(visitor != NULL);
assert(obj != NULL);
assert(obj->clazz != NULL);
visitDataObject(visitor, obj, arg);
size_t offset = gDvm.offJavaLangRefReference_referent;
Object **ref = BYTE_OFFSET(obj, offset);
(*visitor)(ref, arg);
}
/*
* Visits all of the reference stored in an object.
*/
static void visitObject(Visitor *visitor, Object *obj, void *arg)
{
assert(visitor != NULL);
assert(obj != NULL);
assert(obj->clazz != NULL);
if (obj->clazz == gDvm.classJavaLangClass) {
visitClassObject(visitor, obj, arg);
} else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
visitArrayObject(visitor, obj, arg);
} else if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISREFERENCE)) {
visitReferenceObject(visitor, obj, arg);
} else {
visitDataObject(visitor, obj, arg);
}
}
#endif /* _DALVIK_ALLOC_VISITINLINES */