ObjectID ObjectManager::MapToObjectID()

in modules/jpda/src/main/native/jdwp/common/agent/core/ObjectManager.cpp [66:148]


ObjectID ObjectManager::MapToObjectID(JNIEnv* JNIEnvPtr, jobject jvmObject) throw (AgentException) {
    JDWP_TRACE_ENTRY("MapToObjectID(" << JNIEnvPtr << ',' << jvmObject << ')');

    if (jvmObject == NULL) {
        JDWP_TRACE_MAP("## MapToObjectID: map NULL jobject");
        return JDWP_OBJECT_ID_NULL;
    }

    // get object HASH CODE
    jint hashCode = -1;
    if (GetObjectHashCode(jvmObject, &hashCode) != JVMTI_ERROR_NONE) {
        JDWP_TRACE_MAP("## MapToObjectID: GetObjectHashCode failed");
        throw AgentException(JDWP_ERROR_INVALID_OBJECT);
    }

    // get HASH INDEX
    size_t idx = size_t(hashCode) & HASH_TABLE_MSK;

    ObjectID objectID = 0;

    { // LOCK objectID table
    MonitorAutoLock objectIDTableLock(m_objectIDTableMonitor JDWP_FILE_LINE);

    // find EXISTING objectID
    ObjectIDItem* objectIDItem = m_objectIDTable[idx];
    ObjectIDItem* objectIDItemEnd = objectIDItem + m_maxAllocatedObjectID[idx];
    while (objectIDItem != objectIDItemEnd) {
        if (objectIDItem->objectID != FREE_OBJECTID_SIGN &&
            JNIEnvPtr->IsSameObject(objectIDItem->mapObjectIDItem.jvmObject, jvmObject) == JNI_TRUE) {
            objectID = objectIDItem->objectID;
            break;
        }
        objectIDItem++;
    }

    // map NEW objectID if not found existing
    if (objectID == 0) {
        JNIEnvPtr->ExceptionClear();
        jobject newWeakGlobRef = JNIEnvPtr->NewWeakGlobalRef(jvmObject);
        if (newWeakGlobRef == NULL) {
            /* NewWeakGlobalRef() returns NULL for two cases:
             * - requested jobject is garbage collected: here it is not possibly,
             *   as passed jvmObject is local reference and jvmObject can NOT be
             *   garbage collected as long as "live" local reference exists.
             * - the VM runs out of memory and OutOfMemoryExceptionError is thrown - 
             *   suppose just this case is here
            */
            JNIEnvPtr->ExceptionClear();
            JDWP_TRACE_MAP("## MapToObjectID: NewWeakGlobalRef returned NULL");
            throw OutOfMemoryException();
        }
        if (m_freeObjectIDItems[idx] == NULL) {
            // expand table
            size_t objectIDTableOldSize = m_objectIDTableSize[idx];
            m_objectIDTableSize[idx]+= HASH_TABLE_GROW;
            m_objectIDTable[idx] = reinterpret_cast<ObjectIDItem*>
                (AgentBase::GetMemoryManager().Reallocate(m_objectIDTable[idx],
                    OBJECTID_ITEM_SIZE * objectIDTableOldSize,
                    OBJECTID_ITEM_SIZE * m_objectIDTableSize[idx] JDWP_FILE_LINE));
            objectIDItem = m_freeObjectIDItems[idx] = m_objectIDTable[idx] + objectIDTableOldSize;
            objectIDItemEnd = objectIDItem + HASH_TABLE_GROW - 1;
            while (objectIDItem != objectIDItemEnd) {
                objectIDItem->objectID = FREE_OBJECTID_SIGN;
                objectIDItem->nextFreeObjectIDItem = objectIDItem + 1;
                objectIDItem++;
            }
            objectIDItem->objectID = FREE_OBJECTID_SIGN;
            objectIDItem->nextFreeObjectIDItem = NULL;
        }
        objectIDItem = m_freeObjectIDItems[idx];
        m_freeObjectIDItems[idx] = objectIDItem->nextFreeObjectIDItem;
        objectID = objectIDItem - m_objectIDTable[idx] + 1;
        m_maxAllocatedObjectID[idx] = objectID > m_maxAllocatedObjectID[idx] ? objectID : m_maxAllocatedObjectID[idx];
        objectIDItem->objectID = objectID = (objectID << HASH_TABLE_IDX) | idx;
        objectIDItem->mapObjectIDItem.globalRefKind = WEAK_GLOBAL_REF;
        objectIDItem->mapObjectIDItem.jvmObject = newWeakGlobRef;
        objectIDItem->mapObjectIDItem.referencesCount = 0;
    }

    } // UNLOCK objectID table

    return objectID;
} // MapToObjectID()