/*static*/ CreateInstanceProc ClassClosure::calcCreateInstanceProc(VTable* cvtable) { VTable* ivtable = cvtable->ivtable; if (ivtable && ivtable->base) { ScopeChain* scope = cvtable->init->scope(); if (scope->getSize()) { Atom baseAtom = scope->getScope(scope->getSize()-1); if (!AvmCore::isObject(baseAtom)) cvtable->toplevel()->throwVerifyError(kCorruptABCError); ScriptObject* base = AvmCore::atomToScriptObject(baseAtom); // make sure scope object is base type's class object AvmAssert(base->traits()->itraits == cvtable->traits->itraits->base); if (base->traits()->itraits->isAbstractBase) { // If we get here, it means that we descend from an abstract base class, // but don't have a native createInstanceProc of our own; in that case, we // should just create a plain old ScriptObject. (Note that this can // happen for abstract and abstract-restricted; for the latter, we will do // a second check in checkForRestrictedInheritance() and may reject it anyway.) goto create_normal; } // ...otherwise, we're done. ClassClosure* base_cc = base->toClassClosure(); AvmAssert(base_cc != NULL); CreateInstanceProc proc = base_cc->m_createInstanceProc; // If the proc is SemiSealedArrayObject, revert back to normal Array, // and let checkForRestrictedInheritance() choose the proper proc: // we might be a dynamic subclass of a non-dynamic subclass of Array. if (proc == SemiSealedArrayObject::createInstanceProc) proc = ArrayClass::createInstanceProc; // Bugzilla 688486: don't use unsubclassed-specialized // instance creator to create subclassed instances. if (proc == ArrayClass::createUnsubclassedInstanceProc) proc = ArrayClass::createInstanceProc; return proc; } } create_normal: return ClassClosure::createScriptObjectProc; }
void CallStackNode::enumerateScopeChainAtoms(IScopeChainEnumerator& scb) { // First, get the "dynamic" portion of the scope chain, that is, the // part that is modified on-the-fly within the function. This includes // activation objects for try/catch blocks and "with" clauses. if (m_info) { MethodSignaturep const ms = m_info->getMethodSignature(); for (int i = (ms->max_scope() + ms->local_count() - 1), n = ms->local_count(); i >= n; --i) { Atom const scope = m_info->boxOneLocal(m_framep, i, m_traits); AvmAssert(atomKind(scope) != kUnusedAtomTag); // go ahead and call addScope, even if null or undefined. scb.addScope(scope); } } // Next, get the "static" portion of the scope chain, that is, the // part that is defined as part of the definition of the function. This // includes the locals of any functions that enclose this one, and the "this" // object, if any. ScopeChain* scopeChain = m_env ? m_env->scope() : NULL; if (scopeChain) { int scopeChainLength = scopeChain->getSize(); for (int i = scopeChainLength - 1; i >= 0; --i) { Atom scope = scopeChain->getScope(i); if (AvmCore::isObject(scope)) { scb.addScope(scope); } } } }
ClassClosure *SamplerScript::getType(Toplevel* ss_toplevel, SamplerObjectType sot, const void *ptr) { Toplevel* tl; switch (sotGetKind(sot)) { case kSOT_String: { // toplevel can be null here if there was no CodeContext active // when the sample was taken (ie, string was allocated from C++ code). // in that case, use the TL from the SamplerScript itself... it isn't // technically the right one to use, but is adequate for our purposes here // (it will return a stringClass or namespaceClass that will be valid // for the sampler) tl = sotGetToplevel(sot); if (!tl) tl = ss_toplevel; return tl->stringClass(); } case kSOT_Namespace: { tl = sotGetToplevel(sot); if (!tl) tl = ss_toplevel; return tl->namespaceClass(); } default: AvmAssert(0); case kSOT_Object: break; } VTable* vt = sotGetVTable(sot); tl = vt->toplevel(); AvmCore* core = tl->core(); ClassClosure *type; ScriptObject* obj = (ScriptObject*)ptr; if (obj && AvmCore::istype(obj->atom(), core->traits.class_itraits)) { type = tl->classClass(); } else if (obj && AvmCore::istype(obj->atom(), core->traits.function_itraits)) { type = tl->functionClass(); } else if (obj && obj->traits()->isActivationTraits()) { type = tl->objectClass; } else { // fallback answer type = tl->objectClass; // note that note all types will have an init method, // so those types may get reported as "objectClass" rather // than something more specific. However, it's not clear // that the Sampler ever really cared about reporting those // objects well in the first place (eg activation or catch objects), // so it doesn't seem we're a lot worse off than before. ScopeChain* sc = NULL; if (vt->init) sc = vt->init->scope(); if (sc && sc->getSize() <= 1) { if(sc->getSize() == 1) type = tl->classClass(); } else if (sc) { Atom ccAtom = sc->getScope(sc->getSize()-1); if(AvmCore::isObject(ccAtom)) { type = (ClassClosure*) AvmCore::atomToScriptObject(ccAtom); if(!AvmCore::istype(type->atom(), core->traits.class_itraits)) { // obj is a ClassClosure type = tl->classClass(); } } } } AvmAssert(AvmCore::istype(type->atom(), core->traits.class_itraits)); return type; }