diff options
Diffstat (limited to 'vm/alloc/VisitInlines.h')
-rw-r--r-- | vm/alloc/VisitInlines.h | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/vm/alloc/VisitInlines.h b/vm/alloc/VisitInlines.h new file mode 100644 index 0000000..84a456a --- /dev/null +++ b/vm/alloc/VisitInlines.h @@ -0,0 +1,180 @@ +/* + * 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 *classObj; + ClassStatus status; + + assert(visitor != NULL); + assert(obj != NULL); + assert(obj->clazz != NULL); + assert(!strcmp(obj->clazz->descriptor, "Ljava/lang/Class;")); + classObj = (ClassObject *)obj; + (*visitor)(&obj->clazz, arg); + if (IS_CLASS_FLAG_SET(classObj, CLASS_ISARRAY)) { + (*visitor)(&classObj->elementClass, arg); + } + status = classObj->status; + if (status > CLASS_IDX) { + (*visitor)(&classObj->super, arg); + } + (*visitor)(&classObj->classLoader, arg); + visitFields(visitor, obj, arg); + visitStaticFields(visitor, classObj, arg); + if (status > CLASS_IDX) { + visitInterfaces(visitor, classObj, 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 */ |