If we extend a tree along a side exit that knew about fewer global slots that we have now in the tree, merge in the types for those additional slots from the entry map (450535).

This commit is contained in:
Andreas Gal 2008-08-15 16:00:24 -07:00
parent a91faa3c28
commit 31d28b1621

View File

@ -620,6 +620,19 @@ TypeMap::matches(TypeMap& other)
return !memcmp(data(), other.data(), length());
}
/* Use the provided storage area to create a new type map that contains the partial type map
with the rest of it filled up from the complete type map. */
static void
mergeTypeMaps(uint8** partial, unsigned* plength, uint8* complete, unsigned clength, uint8* mem)
{
unsigned l = *plength;
JS_ASSERT(l < clength);
memcpy(mem, *partial, l * sizeof(uint8));
memcpy(mem + l, complete + l, (clength - l) * sizeof(uint8));
*partial = mem;
*plength = clength;
}
TraceRecorder::TraceRecorder(JSContext* cx, GuardRecord* _anchor,
Fragment* _fragment, unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap)
{
@ -660,6 +673,23 @@ TraceRecorder::TraceRecorder(JSContext* cx, GuardRecord* _anchor,
eos_ins = addName(lir->insLoadi(lirbuf->state, offsetof(InterpState, eos)), "eos");
eor_ins = addName(lir->insLoadi(lirbuf->state, offsetof(InterpState, eor)), "eor");
/* If we get a partial list that doesn't have all the types (i.e. recording from a side
exit that was recorded but we added more global slots later), merge the missing types
from the entry type map. This is safe because at the loop edge we verify that we
have compatible types for all globals (entry type and loop edge type match). While
a different trace of the tree might have had a guard with a different type map for
these slots we just filled in here (the guard we continue from didn't know about them),
since we didn't take that particular guard the only way we could have ended up here
is if that other trace had at its end a compatible type distribution with the entry
map. Since thats exactly what we used to fill in the types our current side exit
didn't provide, this is always safe to do. */
unsigned length;
if (ngslots < (length = treeInfo->globalTypeMap.length()))
mergeTypeMaps(&globalTypeMap, &ngslots,
treeInfo->globalTypeMap.data(), length,
(uint8*)alloca(sizeof(uint8) * length));
JS_ASSERT(ngslots == treeInfo->globalTypeMap.length());
/* read into registers all values on the stack and all globals we know so far */
import(treeInfo, lirbuf->sp, ngslots, callDepth, globalTypeMap, stackTypeMap);
}