ScriptEnv* DomainMgr::mapScriptToScriptEnv(DomainEnv* domainEnv, MethodInfo* mi) { ScriptEnv* se = NULL; if (mi != NULL) { se = domainEnv->m_scriptEnvMap->get(mi); if (se == NULL) { // This is an item from a parent domain that's not in the MI->SE map yet. // walk up the parent chain and find it. This can happen if // we find a (cached) entry from a parent Domain; since addNamedScriptEnvs() // only added mappings for the MI/SE's in this Domain/DomainEnv pair, // we won't have the proper mapping. However, we know it must be in // a parent (which is why we start at 1, not 0: no point in looking // in our own map again), so lazily find it. for (uint32_t i = 1, n = domainEnv->m_baseCount; i < n; ++i) { DomainEnv* de = domainEnv->m_bases[i]; if (mi->pool()->domain == de->domain()) { se = de->m_scriptEnvMap->get(mi); AvmAssert(se != NULL); domainEnv->m_scriptEnvMap->add(mi, se); break; } } } // If the MethodInfo was entered, but the script then failed verification, // we might not have a matching ScriptEnv... so don't crash in Debug builds. // (Caller already expects NULL and checks for it.) AvmAssert(se == NULL || se->method == mi); } return se; }
DomainEnv::DomainEnv(AvmCore* core, Domain* domain, DomainEnv* base, uint32_t baseCount) : m_scriptEnvMap(ScriptEnvMap::create(core->GetGC())) , m_domain(domain) , m_globalMemoryScratch(mmfx_new0(Scratch)) , m_globalMemoryBase(m_globalMemoryScratch->scratch) , m_globalMemorySize(GLOBAL_MEMORY_MIN_SIZE) , m_baseCount(baseCount) { WB(core->GetGC(), this, &this->m_bases[0], this); for (uint32_t i = 1; i < baseCount; ++i) { WB(core->GetGC(), this, &this->m_bases[i], base->m_bases[i-1]); } #ifdef _DEBUG GCList<Domain> dl(core->GetGC(), 0); for (Domain* di = m_domain; di != NULL; di = di->base()) dl.add(di); GCList<DomainEnv> el(core->GetGC(), 0); for (DomainEnv* di = this; di != NULL; di = di->base()) el.add(di); AvmAssert(dl.length() == el.length()); for (uint32_t i = 0, n = el.length(); i < n; ++i) { Domain* d = dl[i]; DomainEnv* e = el[i]; AvmAssert(e->domain() == d); } #endif }
void DomainMgr::addNamedScriptEnvs(AbcEnv* abcEnv, const GCList<ScriptEnv>& envs) { // If the MethodInfo for this ScriptEnv isn't in the Domain's or Pool's // map, then we must have filtered it out as unreachable: don't // bother adding the ScriptEnv, as we'll never need to look it up. // (Note that we don't need to bother checking the parent Domains // for this, since we want to check loaded, not cached.) We can't rely // on looking up by name, since scripts all tend to be named "global", // so instead we make a temporary map of all the entries in the relevant // Pool and Domain. PoolObject* pool = abcEnv->pool(); DomainEnv* domainEnv = abcEnv->domainEnv(); Domain* domain = domainEnv->domain(); // we have no generic "set" type, so let's use a hashtable for the same purpose // (a bit more mem, but short-lived and better average lookup time than using List<>) HeapHashtable* ht = HeapHashtable::create(core->GetGC()); for (StMNHTMethodInfoIterator iter(pool->m_loadedScripts); iter.next(); ) { if (!iter.key()) continue; Atom const a = AvmCore::genericObjectToAtom(iter.value()); ht->add(a, a); } for (StMNHTMethodInfoIterator iter(domain->m_loadedScripts); iter.next(); ) { if (!iter.key()) continue; Atom const a = AvmCore::genericObjectToAtom(iter.value()); ht->add(a, a); } for (uint32_t i = 0, n = envs.length(); i < n; ++i) { ScriptEnv* se = envs[i]; AvmAssert(se->abcEnv() == abcEnv); MethodInfo* mi = se->method; AvmAssert(domainEnv->m_scriptEnvMap->get(mi) == NULL); if (ht->get(AvmCore::genericObjectToAtom(mi)) == undefinedAtom) continue; domainEnv->m_scriptEnvMap->add(mi, se); } delete ht; }