int32_t GCConfigTest::processObjNode(pugi::xml_node node, const char *namePrefixStr, OMRGCObjectType objType, AttributeElem *numOfFieldsElem, AttributeElem *breadthElem, int32_t depth) { OMRPORT_ACCESS_FROM_OMRPORT(gcTestEnv->portLib); int32_t rt = 0; OMR_VM *omrVMPtr = exampleVM->_omrVM; int32_t numOfParents = 0; /* Create objects and store them in the root table or the slot object based on objType. */ if ((ROOT == objType) || (GARBAGE_ROOT == objType)) { for (int32_t i = 0; i < breadthElem->value; i++) { omrobjectptr_t obj; char *objName = NULL; uintptr_t sizeCalculated = numOfFieldsElem->value * sizeof(fomrobject_t) + sizeof(uintptr_t); rt = createObject(&obj, &objName, namePrefixStr, objType, 0, i, sizeCalculated); OMRGCTEST_CHECK_RT(rt); numOfFieldsElem = numOfFieldsElem->linkNext; /* Add object to root hash table. If it's the root of the garbage tree, temporarily keep it as root for allocating * the rest of the tree. Remove it from the root set after the entire garbage tree is allocated.*/ RootEntry rEntry; rEntry.name = objName; rEntry.rootPtr = obj; if (NULL == hashTableAdd(exampleVM->rootTable, &rEntry)) { rt = 1; omrtty_printf("%s:%d Failed to add new root entry to root table!\n", __FILE__, __LINE__); goto done; } /* insert garbage per node */ if ((ROOT == objType) && (0 == strcmp(gp.frequency, "perObject"))) { rt = insertGarbage(); OMRGCTEST_CHECK_RT(rt); } } } else if ((NORMAL == objType) || (GARBAGE_TOP == objType) || (GARBAGE_CHILD == objType)) { char parentName[MAX_NAME_LENGTH]; omrstr_printf(parentName, MAX_NAME_LENGTH, "%s_%d_%d", node.parent().attribute("namePrefix").value(), 0, 0); ObjectEntry *parentEntry; rt = objectTable.find(&parentEntry, parentName); if (0 != rt) { omrtty_printf("%s:%d Could not find object %s in hash table.\n", __FILE__, __LINE__, parentName); goto done; } omrobjectptr_t parent = parentEntry->objPtr; GC_ObjectIterator objectIterator(omrVMPtr, parent); objectIterator.restore(parentEntry->numOfRef); for (int32_t i = 0; i < breadthElem->value; i++) { omrobjectptr_t obj; char *objName = NULL; uintptr_t sizeCalculated = numOfFieldsElem->value * sizeof(fomrobject_t) + sizeof(uintptr_t); rt = createObject(&obj, &objName, namePrefixStr, objType, 0, i, sizeCalculated); OMRGCTEST_CHECK_RT(rt); numOfFieldsElem = numOfFieldsElem->linkNext; GC_SlotObject *slotObject = NULL; if (NULL != (slotObject = objectIterator.nextSlot())) { #if defined(OMRGCTEST_DEBUG) omrtty_printf("\tadd to slot of parent(%llu) %d\n", parent, parentEntry->numOfRef + i); #endif /* Add object to parent's slot. If it's the top of the garbage tree, temporarily keep it in the slot until * the rest of the tree is allocated. */ slotObject->writeReferenceToSlot(obj); } else { rt = 1; omrtty_printf("%s:%d Invalid XML input: numOfFields defined for %s is not enough to hold all children references.\n", __FILE__, __LINE__, parentName); goto done; } /* insert garbage per node */ if ((NORMAL == objType) && (0 == strcmp(gp.frequency, "perObject"))) { rt = insertGarbage(); OMRGCTEST_CHECK_RT(rt); } } parentEntry->numOfRef += breadthElem->value; } else { rt = 1; goto done; } /* Create the rest of the tree, if any, defined with depth. First, we set the child object with correct objType. */ if (ROOT == objType) { objType = NORMAL; } else if ((GARBAGE_TOP == objType) || (GARBAGE_ROOT == objType)) { objType = GARBAGE_CHILD; } numOfParents = breadthElem->value; breadthElem = breadthElem->linkNext; for (int32_t i = 1; i < depth; i++) { int32_t nthInRow = 0; for (int32_t j = 0; j < numOfParents; j++) { char parentName[MAX_NAME_LENGTH]; omrstr_printf(parentName, sizeof(parentName), "%s_%d_%d", namePrefixStr, (i - 1), j); ObjectEntry *parentEntry; rt = objectTable.find(&parentEntry, parentName); if (0 != rt) { omrtty_printf("%s:%d Could not find object %s in hash table.\n", __FILE__, __LINE__, parentName); goto done; } omrobjectptr_t parent = parentEntry->objPtr; GC_ObjectIterator objectIterator(omrVMPtr, parent); objectIterator.restore(parentEntry->numOfRef); for (int32_t k = 0; k < breadthElem->value; k++) { omrobjectptr_t obj; char *objName = NULL; uintptr_t sizeCalculated = numOfFieldsElem->value * sizeof(fomrobject_t) + sizeof(uintptr_t); rt = createObject(&obj, &objName, namePrefixStr, objType, i, nthInRow, sizeCalculated); OMRGCTEST_CHECK_RT(rt); numOfFieldsElem = numOfFieldsElem->linkNext; nthInRow += 1; GC_SlotObject *slotObject = NULL; if (NULL != (slotObject = objectIterator.nextSlot())) { #if defined(OMRGCTEST_DEBUG) omrtty_printf("\tadd to parent(%llu) slot %d.\n", parent, parentEntry->numOfRef + k); #endif slotObject->writeReferenceToSlot(obj); } else { rt = 1; omrtty_printf("%s:%d Invalid XML input: numOfFields defined for %s is not enough to hold all children references.\n", __FILE__, __LINE__, parentName); goto done; } /* insert garbage per node */ if ((NORMAL == objType) && (0 == strcmp(gp.frequency, "perObject"))) { rt = insertGarbage(); OMRGCTEST_CHECK_RT(rt); } } parentEntry->numOfRef += breadthElem->value; } numOfParents = nthInRow; breadthElem = breadthElem->linkNext; } done: return rt; }
int32_t GCConfigTest::allocationWalker(pugi::xml_node node) { OMRPORT_ACCESS_FROM_OMRVM(exampleVM->_omrVM); int32_t rt = 0; AttributeElem *numOfFieldsElem = NULL; AttributeElem *breadthElem = NULL; int32_t depth = 0; OMRGCObjectType objType = INVALID; const char *namePrefixStr = node.attribute("namePrefix").value(); const char *numOfFieldsStr = node.attribute("numOfFields").value(); const char *typeStr = node.attribute("type").value(); const char *breadthStr = node.attribute("breadth").value(); const char *depthStr = node.attribute("depth").value(); if (0 != strcmp(node.name(), "object")) { /* allow non-object node nested inside allocation? */ goto done; } if ((0 == strcmp(namePrefixStr, "")) || (0 == strcmp(typeStr, "")) || (0 == strcmp(numOfFieldsStr, ""))) { rt = 1; omrtty_printf("%s:%d Invalid XML input: please specify namePrefix, type and numOfFields for object %s.\n", __FILE__, __LINE__, namePrefixStr); goto done; } /* set default value for breadth and depth to 1 */ if (0 == strcmp(breadthStr, "")) { breadthStr = "1"; } if (0 == strcmp(depthStr, "")) { depthStr = "1"; } depth = atoi(depthStr); objType = parseObjectType(node); rt = parseAttribute(&numOfFieldsElem, numOfFieldsStr); OMRGCTEST_CHECK_RT(rt) rt = parseAttribute(&breadthElem, breadthStr); OMRGCTEST_CHECK_RT(rt); /* process current xml node, perform allocation for single object or object tree */ rt = processObjNode(node, namePrefixStr, objType, numOfFieldsElem, breadthElem, depth); OMRGCTEST_CHECK_RT(rt); /* only single object can contain nested child object */ if ((0 == strcmp(breadthStr, "1")) && (0 == strcmp(depthStr, "1"))) { for (pugi::xml_node childNode = node.first_child(); childNode; childNode = childNode.next_sibling()) { rt = allocationWalker(childNode); OMRGCTEST_CHECK_RT(rt); } } /* After the entire garbage tree is allocated, remove garbage root object from the root set * or remove garbage top object from the slot of its parent object. */ if (GARBAGE_ROOT == objType) { for (int32_t i = 0; i < breadthElem->value; i++) { char objName[MAX_NAME_LENGTH]; omrstr_printf(objName, MAX_NAME_LENGTH, "%s_%d_%d", namePrefixStr, 0, i); rt = removeObjectFromRootTable(objName); OMRGCTEST_CHECK_RT(rt); } } else if (GARBAGE_TOP == objType) { char parentName[MAX_NAME_LENGTH]; omrstr_printf(parentName, MAX_NAME_LENGTH, "%s_%d_%d", node.parent().attribute("namePrefix").value(), 0, 0); ObjectEntry *parentEntry; rt = objectTable.find(&parentEntry, parentName); if (0 != rt) { omrtty_printf("%s:%d Could not find object %s in hash table.\n", __FILE__, __LINE__, parentName); goto done; } omrobjectptr_t parentPtr = parentEntry->objPtr; for (int32_t i = 0; i < breadthElem->value; i++) { char objName[MAX_NAME_LENGTH]; omrstr_printf(objName, MAX_NAME_LENGTH, "%s_%d_%d", namePrefixStr, 0, i); rt = removeObjectFromParentSlot(objName, parentPtr); OMRGCTEST_CHECK_RT(rt); } } /* insert garbage per tree */ if ((0 == strcmp(gp.frequency, "perRootStruct")) && (ROOT == objType)){ rt = insertGarbage(); OMRGCTEST_CHECK_RT(rt); } done: freeAttributeList(breadthElem); freeAttributeList(numOfFieldsElem); return rt; }
int32_t GCConfigTest::processObjNode(pugi::xml_node node, const char *namePrefixStr, OMRGCObjectType objType, AttributeElem *numOfFieldsElem, AttributeElem *breadthElem, int32_t depth) { OMRPORT_ACCESS_FROM_OMRPORT(gcTestEnv->portLib); int32_t rt = 1; int32_t numOfParents = 0; /* Create objects and store them in the root table or the slot object based on objType. */ if ((ROOT == objType) || (GARBAGE_ROOT == objType)) { for (int32_t i = 0; i < breadthElem->value; i++) { uintptr_t sizeCalculated = numOfFieldsElem->value * sizeof(fomrobject_t) + sizeof(uintptr_t); ObjectEntry *objectEntry = createObject(namePrefixStr, objType, 0, i, sizeCalculated); if (NULL == objectEntry) { goto done; } numOfFieldsElem = numOfFieldsElem->linkNext; /* Add object to root hash table. If it's the root of the garbage tree, temporarily keep it as root for allocating * the rest of the tree. Remove it from the root set after the entire garbage tree is allocated.*/ RootEntry rEntry; rEntry.name = objectEntry->name; rEntry.rootPtr = objectEntry->objPtr; if (NULL == hashTableAdd(exampleVM->rootTable, &rEntry)) { omrtty_printf("%s:%d Failed to add new root entry to root table!\n", __FILE__, __LINE__); goto done; } /* insert garbage per node */ if ((ROOT == objType) && (0 == strcmp(gp.frequency, "perObject"))) { int32_t grt = insertGarbage(); OMRGCTEST_CHECK_RT(grt); } } } else if ((NORMAL == objType) || (GARBAGE_TOP == objType) || (GARBAGE_CHILD == objType)) { char parentName[MAX_NAME_LENGTH]; omrstr_printf(parentName, MAX_NAME_LENGTH, "%s_%d_%d", node.parent().attribute("namePrefix").value(), 0, 0); for (int32_t i = 0; i < breadthElem->value; i++) { uintptr_t sizeCalculated = numOfFieldsElem->value * sizeof(fomrobject_t) + sizeof(uintptr_t); ObjectEntry *childEntry = createObject(namePrefixStr, objType, 0, i, sizeCalculated); if (NULL == childEntry) { goto done; } ObjectEntry *parentEntry = find(parentName); if (NULL == parentEntry) { omrtty_printf("%s:%d Could not find object %s in hash table.\n", __FILE__, __LINE__, parentName); goto done; } if (0 != attachChildEntry(parentEntry, childEntry)) { goto done; } numOfFieldsElem = numOfFieldsElem->linkNext; /* insert garbage per node */ if ((NORMAL == objType) && (0 == strcmp(gp.frequency, "perObject"))) { int32_t grt = insertGarbage(); OMRGCTEST_CHECK_RT(grt); } } } else { goto done; } /* Create the rest of the tree, if any, defined with depth. First, we set the child object with correct objType. */ if (ROOT == objType) { objType = NORMAL; } else if ((GARBAGE_TOP == objType) || (GARBAGE_ROOT == objType)) { objType = GARBAGE_CHILD; } numOfParents = breadthElem->value; breadthElem = breadthElem->linkNext; for (int32_t i = 1; i < depth; i++) { int32_t nthInRow = 0; for (int32_t j = 0; j < numOfParents; j++) { char parentName[MAX_NAME_LENGTH]; omrstr_printf(parentName, sizeof(parentName), "%s_%d_%d", namePrefixStr, (i - 1), j); for (int32_t k = 0; k < breadthElem->value; k++) { uintptr_t sizeCalculated = sizeof(omrobjectptr_t) + numOfFieldsElem->value * sizeof(fomrobject_t); ObjectEntry *childEntry = createObject(namePrefixStr, objType, i, nthInRow, sizeCalculated); if (NULL == childEntry) { goto done; } ObjectEntry *parentEntry = find(parentName); if (NULL == parentEntry) { omrtty_printf("%s:%d Could not find object %s in hash table.\n", __FILE__, __LINE__, parentName); goto done; } if (0 != attachChildEntry(parentEntry, childEntry)) { goto done; } numOfFieldsElem = numOfFieldsElem->linkNext; nthInRow += 1; /* insert garbage per node */ if ((NORMAL == objType) && (0 == strcmp(gp.frequency, "perObject"))) { int32_t grt = insertGarbage(); OMRGCTEST_CHECK_RT(grt); } } } numOfParents = nthInRow; breadthElem = breadthElem->linkNext; } rt = 0; done: return rt; }