Example #1
0
/**
 * Take in a collection of exclusive sub engines and produces a tamarama, also
 * returns via out_top_remap, a mapping indicating how tops in the subengines in
 * relate to the tamarama's tops.
 */
aligned_unique_ptr<NFA> buildTamarama(const TamaInfo &tamaInfo, const u32 queue,
                        map<pair<const NFA *, u32>, u32> &out_top_remap) {
    vector<u32> top_base;
    remapTops(tamaInfo, top_base, out_top_remap);

    size_t subSize = tamaInfo.subengines.size();
    DEBUG_PRINTF("subSize:%lu\n", subSize);
    size_t total_size =
        sizeof(NFA) +               // initial NFA structure
        sizeof(Tamarama) +          // Tamarama structure
        sizeof(u32) * subSize +     // base top event value for subengines,
                                    // used for top remapping at runtime
        sizeof(u32) * subSize + 64; // offsets to subengines in bytecode and
                                    // padding for subengines

    for (const auto &sub : tamaInfo.subengines) {
        total_size += ROUNDUP_CL(sub->length);
    }

    // use subSize as a sentinel value for no active subengines,
    // so add one to subSize here
    u32 activeIdxSize = calcPackedBytes(subSize + 1);
    aligned_unique_ptr<NFA> nfa = aligned_zmalloc_unique<NFA>(total_size);
    nfa->type = verify_u8(TAMARAMA_NFA_0);
    nfa->length = verify_u32(total_size);
    nfa->queueIndex = queue;

    char *ptr = (char *)nfa.get() + sizeof(NFA);
    char *base_offset = ptr;
    Tamarama *t = (Tamarama *)ptr;
    t->numSubEngines = verify_u32(subSize);
    t->activeIdxSize = verify_u8(activeIdxSize);

    ptr += sizeof(Tamarama);
    copy_bytes(ptr, top_base);
    ptr += byte_length(top_base);

    u32 *offsets = (u32*)ptr;
    char *sub_nfa_offset = ptr + sizeof(u32) * subSize;
    copyInSubnfas(base_offset, *nfa, tamaInfo, offsets, sub_nfa_offset,
                  activeIdxSize);
    assert((size_t)(sub_nfa_offset - (char *)nfa.get()) <= total_size);
    return nfa;
}
Example #2
0
RepeatStateInfo::RepeatStateInfo(enum RepeatType type, const depth &repeatMin,
                                 const depth &repeatMax, u32 minPeriod)
    : stateSize(0), packedCtrlSize(0), horizon(0), patchCount(0),
      patchSize(0), encodingSize(0), patchesOffset(0) {
    assert(repeatMin <= repeatMax);
    assert(repeatMax.is_reachable());
    assert(minPeriod || type != REPEAT_SPARSE_OPTIMAL_P);

    switch (type) {
    case REPEAT_FIRST:
        assert(repeatMin.is_finite());
        stateSize = 0; // everything is in the control block.
        horizon = repeatMin;
        packedCtrlSize = calcPackedBytes(horizon + 1);
        break;
    case REPEAT_LAST:
        assert(repeatMax.is_finite());
        stateSize = 0; // everything is in the control block.
        horizon = repeatMax + 1;
        packedCtrlSize = calcPackedBytes(horizon + 1);
        break;
    case REPEAT_RING:
        assert(repeatMax.is_finite());
        stateSize = mmbit_size(repeatMax + 1);
        horizon = repeatMax * 2 + 1; /* TODO: investigate tightening */
        // Packed offset member, plus two bytes for each ring index, reduced to
        // one byte each if they'll fit in eight bits.
        {
            u32 offset_len = calcPackedBytes(horizon + 1);
            u32 ring_indices_len = repeatMax < depth(254) ? 2 : 4;
            packedCtrlSize = offset_len + ring_indices_len;
        }
        break;
    case REPEAT_RANGE:
        assert(repeatMax.is_finite());
        assert(repeatMin < repeatMax);
        stateSize = numRangeSlots(repeatMin, repeatMax) * sizeof(u16);
        horizon = repeatMax * 2 + 1;
        // Packed offset member, plus one byte for the number of range
        // elements.
        packedCtrlSize = calcPackedBytes(horizon + 1) + 1;
        break;
    case REPEAT_BITMAP:
        stateSize = 0; // everything is in the control block.
        horizon = 0;   // unused
        packedCtrlSize = ROUNDUP_N(repeatMax + 1, 8) / 8;
        break;
    case REPEAT_SPARSE_OPTIMAL_P:
        assert(minPeriod);
        assert(repeatMax.is_finite());
        {
            u32 rv = repeatRecurTable(this, repeatMax, minPeriod);
            u32 repeatTmp = 0;
            if ((u32)repeatMax < minPeriod) {
                repeatTmp = repeatMax;
                patchCount = 1;
            } else {
                // find optimal patch size
                repeatTmp =
                    findOptimalPatchSize(this, repeatMax, minPeriod, rv);
                assert(patchCount < 65536);
            }
            DEBUG_PRINTF("repeat[%u %u], period=%u\n", (u32)repeatMin,
                         (u32)repeatMax, minPeriod);
            u64a maxVal = table[repeatTmp];
            encodingSize = calcPackedBytes(maxVal);
            patchSize = repeatTmp;
            assert(encodingSize <= 64);

            patchesOffset = mmbit_size(patchCount);
            stateSize = patchesOffset + encodingSize * patchCount;
            horizon = (repeatTmp * patchCount) * 2 + 1;
            u32 ring_indices_len = patchCount < depth(254) ? 2 : 4;
            packedCtrlSize = calcPackedBytes(horizon + 1) + ring_indices_len;
        }
        break;
    case REPEAT_TRAILER:
        assert(repeatMax.is_finite());
        assert(repeatMin <= depth(64));
        stateSize = 0; // everything is in the control block.
        horizon = repeatMax + 1;
        packedFieldSizes.resize(2);
        packedFieldSizes[0] = calcPackedBits(horizon + 1);
        packedFieldSizes[1] = repeatMin;
        packedCtrlSize = (packedFieldSizes[0] + packedFieldSizes[1] + 7U) / 8U;
        break;
    }
    DEBUG_PRINTF("stateSize=%u, packedCtrlSize=%u, horizon=%u\n", stateSize,
                 packedCtrlSize, horizon);

    assert(packedCtrlSize <= sizeof(RepeatControl));
}