rem: for (i = sizeof (dtrace_aggid_t); i < size; i++) { hashval += data[i]; hashval += (hashval << 10); hashval ^= (hashval >> 6);
add: for (act = agg->dtag_first; act->dta_intuple; act = act->dta_next) { i = act->dta_rec.dtrd_offset - agg->dtag_base; limit = i + act->dta_rec.dtrd_size; ASSERT(limit <= size); isstr = DTRACEACT_ISSTRING(act);  for (; i < limit; i++) { hashval += data[i]; hashval += (hashval << 10); hashval ^= (hashval >> 6);  if (isstr && data[i] == '\0') break; }
context: dtrace_aggregate(dtrace_aggregation_t *agg, dtrace_buffer_t *dbuf,    intptr_t offset, dtrace_buffer_t *buf, uint64_t expr, uint64_t arg){	dtrace_recdesc_t *rec = &agg->dtag_action.dta_rec;	uint32_t i, ndx, size, fsize;	uint32_t align = sizeof (uint64_t) - 1;	dtrace_aggbuffer_t *agb;	dtrace_aggkey_t *key;	uint32_t hashval = 0;	caddr_t tomax, data, kdata;	dtrace_actkind_t action;	uintptr_t offs;	if (buf == NULL)		return;	if (!agg->dtag_hasarg) {		/*		 * Currently, only quantize() and lquantize() take additional		 * arguments, and they have the same semantics:  an increment		 * value that defaults to 1 when not present.  If additional		 * aggregating actions take arguments, the setting of the		 * default argument value will presumably have to become more		 * sophisticated...		 */		arg = 1;	}	action = agg->dtag_action.dta_kind - DTRACEACT_AGGREGATION;	size = rec->dtrd_offset - agg->dtag_base;	fsize = size + rec->dtrd_size;	ASSERT(dbuf->dtb_tomax != NULL);	data = dbuf->dtb_tomax + offset + agg->dtag_base;	if ((tomax = buf->dtb_tomax) == NULL) {		dtrace_buffer_drop(buf);		return;	}	/*	 * The metastructure is always at the bottom of the buffer.	 */	agb = (dtrace_aggbuffer_t *)(tomax + buf->dtb_size -	    sizeof (dtrace_aggbuffer_t));	if (buf->dtb_offset == 0) {		/*		 * We just kludge up approximately 1/8th of the size to be		 * buckets.  If this guess ends up being routinely		 * off-the-mark, we may need to dynamically readjust this		 * based on past performance.		 */		uintptr_t hashsize = (buf->dtb_size >> 3) / sizeof (uintptr_t);		if ((uintptr_t)agb - hashsize * sizeof (dtrace_aggkey_t *) <		    (uintptr_t)tomax || hashsize == 0) {			/*			 * We've been given a ludicrously small buffer;			 * increment our drop count and leave.			 */			dtrace_buffer_drop(buf);			return;		}		/*		 * And now, a pathetic attempt to try to get a an odd (or		 * perchance, a prime) hash size for better hash distribution.		 */		if (hashsize > (DTRACE_AGGHASHSIZE_SLEW << 3))			hashsize -= DTRACE_AGGHASHSIZE_SLEW;		agb->dtagb_hashsize = hashsize;		agb->dtagb_hash = (dtrace_aggkey_t **)((uintptr_t)agb -		    agb->dtagb_hashsize * sizeof (dtrace_aggkey_t *));		agb->dtagb_free = (uintptr_t)agb->dtagb_hash;		for (i = 0; i < agb->dtagb_hashsize; i++)			agb->dtagb_hash[i] = NULL;	}	/*	 * Calculate the hash value based on the key.  Note that we _don't_	 * include the aggid in the hashing (but we will store it as part of	 * the key).  The hashing algorithm is Bob Jenkins' "One-at-a-time"	 * algorithm: a simple, quick algorithm that has no known funnels, and	 * gets good distribution in practice.  The efficacy of the hashing	 * algorithm (and a comparison with other algorithms) may be found by	 * running the ::dtrace_aggstat MDB dcmd.	 */	for (i = sizeof (dtrace_aggid_t); i < size; i++) {		hashval += data[i];		hashval += (hashval << 10);		hashval ^= (hashval >> 6);	}	hashval += (hashval << 3);	hashval ^= (hashval >> 11);	hashval += (hashval << 15);	/*	 * Yes, the divide here is expensive.  If the cycle count here becomes	 * prohibitive, we can do tricks to eliminate it.	 */	ndx = hashval % agb->dtagb_hashsize;	for (key = agb->dtagb_hash[ndx]; key != NULL; key = key->dtak_next) {		ASSERT((caddr_t)key >= tomax);		ASSERT((caddr_t)key < tomax + buf->dtb_size);		if (hashval != key->dtak_hashval || key->dtak_size != size)			continue;		kdata = key->dtak_data;		ASSERT(kdata >= tomax && kdata < tomax + buf->dtb_size);		for (i = sizeof (dtrace_aggid_t); i < size; i++) {			if (kdata[i] != data[i])				goto next;		}		if (action != key->dtak_action) {			/*			 * We are aggregating on the same value in the same			 * aggregation with two different aggregating actions.			 * (This should have been picked up in the compiler,			 * so we may be dealing with errant or devious DIF.)			 * This is an error condition; we indicate as much,			 * and return.			 */			DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);			return;		}		/*		 * This is a hit:  we need to apply the aggregator to		 * the value at this key.		 */		agg->dtag_aggregate((uint64_t *)(kdata + size), expr, arg);		return;next:		continue;	}	/*	 * We didn't find it.  We need to allocate some zero-filled space,	 * link it into the hash table appropriately, and apply the aggregator	 * to the (zero-filled) value.	 */	offs = buf->dtb_offset;	while (offs & (align - 1))		offs += sizeof (uint32_t);	/*	 * If we don't have enough room to both allocate a new key _and_	 * its associated data, increment the drop count and return.	 */	if ((uintptr_t)tomax + offs + fsize >	    agb->dtagb_free - sizeof (dtrace_aggkey_t)) {		dtrace_buffer_drop(buf);		return;	}	/*CONSTCOND*/	ASSERT(!(sizeof (dtrace_aggkey_t) & (sizeof (uintptr_t) - 1)));	key = (dtrace_aggkey_t *)(agb->dtagb_free - sizeof (dtrace_aggkey_t));	agb->dtagb_free -= sizeof (dtrace_aggkey_t);	key->dtak_data = kdata = tomax + offs;	buf->dtb_offset = offs + fsize;	/*	 * Now copy the data across.	 */	*((dtrace_aggid_t *)kdata) = agg->dtag_id;	for (i = sizeof (dtrace_aggid_t); i < size; i++)		kdata[i] = data[i];	for (i = size; i < fsize; i++)		kdata[i] = 0;	key->dtak_hashval = hashval;	key->dtak_size = size;	key->dtak_action = action;	key->dtak_next = agb->dtagb_hash[ndx];	agb->dtagb_hash[ndx] = key;	/*	 * Finally, apply the aggregator.	 */	*((uint64_t *)(key->dtak_data + size)) = agg->dtag_initial;	agg->dtag_aggregate((uint64_t *)(key->dtak_data + size), expr, arg);}