/** * 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; }
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)); }