diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 6542c196579..9d65ed01418 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -1308,6 +1308,19 @@ TypeMap::matches(TypeMap& other) const 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; +} + /* Specializes a tree to any missing globals, including any dependent trees. */ static JS_REQUIRES_STACK void specializeTreesToMissingGlobals(JSContext* cx, TreeInfo* root) @@ -2077,16 +2090,29 @@ JS_REQUIRES_STACK void TraceRecorder::import(TreeInfo* treeInfo, LIns* sp, unsigned stackSlots, unsigned ngslots, unsigned callDepth, uint8* typeMap) { + /* 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. */ + + uint8* globalTypeMap = typeMap + stackSlots; + unsigned length = treeInfo->nGlobalTypes(); + /* - * If we get a partial list that doesn't have all the types, capture the missing types - * from the current environment. + * This is potentially the typemap of the side exit and thus shorter than the tree's + * global type map. */ - TypeMap fullTypeMap(typeMap, stackSlots + ngslots); - if (ngslots < treeInfo->globalSlots->length()) { - fullTypeMap.captureMissingGlobalTypes(cx, *treeInfo->globalSlots, stackSlots); - ngslots = treeInfo->globalSlots->length(); + if (ngslots < length) { + mergeTypeMaps(&globalTypeMap/*out param*/, &ngslots/*out param*/, + treeInfo->globalTypeMap(), length, + (uint8*)alloca(sizeof(uint8) * length)); } - uint8* globalTypeMap = fullTypeMap.data() + stackSlots; JS_ASSERT(ngslots == treeInfo->nGlobalTypes()); /* diff --git a/js/src/jstracer.h b/js/src/jstracer.h index 9f709e6fd2a..3ae2587fd06 100644 --- a/js/src/jstracer.h +++ b/js/src/jstracer.h @@ -76,13 +76,6 @@ public: this->_data = (T*)malloc(max * sizeof(T)); } - Queue(T* data, unsigned length) { - this->_max = - this->_len = length; - this->_data = (T*)malloc(length * sizeof(T)); - memcpy(this->_data, data, length); - } - ~Queue() { free(_data); } @@ -196,12 +189,6 @@ typedef Queue SlotList; class TypeMap : public Queue { public: - TypeMap() : Queue() { - } - - TypeMap(uint8* partial, unsigned length) : Queue(partial, length) { - } - JS_REQUIRES_STACK void captureTypes(JSContext* cx, SlotList& slots, unsigned callDepth); JS_REQUIRES_STACK void captureMissingGlobalTypes(JSContext* cx, SlotList& slots,