VTable* VTable::newParameterizedVTable(Traits* param_traits, Stringp fullname) { Toplevel* toplevel = this->toplevel(); AvmCore* core = toplevel->core(); Namespacep traitsNs = this->traits->ns(); GCRef<builtinClassManifest> builtinClasses = toplevel->builtinClasses(); GCRef<ObjectVectorClass> vectorobj_cls = builtinClasses->get_Vector_objectClass(); GCRef<ScopeChain> vectorobj_cscope = vectorobj_cls->vtable->init->scope(); GCRef<ScopeChain> vectorobj_iscope = vectorobj_cls->ivtable()->init->scope(); VTable* objVecVTable = vectorobj_cls->vtable; AbcEnv* objVecAbcEnv = vectorobj_cscope->abcEnv(); Toplevel* objVecToplevel = objVecVTable->toplevel(); VTable* objVecIVTable = objVecVTable->ivtable; // these cases should all be filtered out by the caller; // we only want to handle Vector<SomeObject> here AvmAssert(param_traits != NULL && param_traits != toplevel->intClass()->vtable->traits->itraits && param_traits != toplevel->uintClass()->vtable->traits->itraits && param_traits != toplevel->numberClass()->vtable->traits->itraits); PoolObject* traitsPool = this->traits->pool; Stringp classname = core->internString(fullname->appendLatin1("$")); Traits* ctraits = core->domainMgr()->findTraitsInPoolByNameAndNS(traitsPool, classname, traitsNs); Traits* itraits; if (!ctraits) { // important: base the new ctraits on objVecVTable->traits, *not* this->traits; // we want the result to be based off ObjectVectorClass, not VectorClass // (otherwise sizeofInstance would be too small and we'd be crashy) ctraits = objVecVTable->traits->newParameterizedCTraits(classname, traitsNs); ctraits->verifyBindings(toplevel); itraits = traitsPool->resolveParameterizedType(toplevel, this->ivtable->traits, param_traits); ctraits->itraits = itraits; } else { itraits = ctraits->itraits; } AvmAssert(itraits != NULL); VTable* class_ivtable = builtinClasses->get_ClassClass()->ivtable(); VTable* cvtab = core->newVTable(ctraits, class_ivtable, objVecToplevel); ScopeChain* cvtab_cscope = vectorobj_cscope->cloneWithNewVTable(core->GetGC(), cvtab, objVecAbcEnv); VTable* ivtab = core->newVTable(itraits, objVecIVTable, objVecToplevel); ScopeChain* ivtab_iscope = vectorobj_iscope->cloneWithNewVTable(core->GetGC(), ivtab, objVecAbcEnv); cvtab->ivtable = ivtab; ivtab->init = objVecIVTable->init; cvtab->resolveSignatures(cvtab_cscope); ivtab->resolveSignatures(ivtab_iscope); return cvtab; }
double SamplerScript::_getInvocationCount(ScriptObject* self, Atom a, QNameObject* qname, uint32_t type) { #ifdef DEBUGGER AvmCore* core = self->core(); Sampler* s = core->get_sampler(); if (!s || !trusted(self)) return -1; Multiname multiname; if(qname) qname->getMultiname(multiname); ScriptObject* object = self->toplevel()->global(); if(!AvmCore::isObject(a)) { // not sure if this will be true for standalone avmplus AvmAssert(core->codeContext() != NULL); DomainEnv *domainEnv = core->codeContext()->domainEnv(); ScriptEnv* script = (ScriptEnv*) core->domainMgr()->findScriptEnvInDomainEnvByMultiname(domainEnv, multiname); if (script != (ScriptEnv*)BIND_NONE) { if (script == (ScriptEnv*)BIND_AMBIGUOUS) self->toplevel()->throwReferenceError(kAmbiguousBindingError, &multiname); object = script->global; if (object == NULL) { object = script->initGlobal(); script->coerceEnter(script->global->atom()); } } } else { object = AvmCore::atomToScriptObject(a); if(AvmCore::istype(a, CLASS_TYPE) && !qname) { // return constructor count ClassClosure *cc = (ClassClosure*)object; if (cc->vtable->init) // Vector related crash here, Tommy says: I didn't think a type could ever not have a constructor but I guess there's no reason it has to. return (double)cc->vtable->init->invocationCount(); } } if(!object || !qname) return -1; VTable *v = object->vtable; again: MethodEnv *env = NULL; Binding b = self->toplevel()->getBinding(v->traits, &multiname); switch (AvmCore::bindingKind(b)) { case BKIND_VAR: case BKIND_CONST: { // only look at slots for first pass, otherwise we're applying instance traits to the Class if(v == object->vtable) { Atom method = object->getSlotAtom(AvmCore::bindingToSlotId(b)); if(AvmCore::isObject(method)) { env = AvmCore::atomToScriptObject(method)->getCallMethodEnv(); } } break; } case BKIND_METHOD: { int m = AvmCore::bindingToMethodId(b); env = v->methods[m]; break; } case BKIND_GET: case BKIND_GETSET: case BKIND_SET: { if(type == GET && AvmCore::hasGetterBinding(b)) env = v->methods[AvmCore::bindingToGetterId(b)]; else if(type == SET && AvmCore::hasSetterBinding(b)) env = v->methods[AvmCore::bindingToSetterId(b)]; break; } case BKIND_NONE: { Atom method = object->getStringProperty(multiname.getName()); if(AvmCore::isObject(method)) { env = AvmCore::atomToScriptObject(method)->getCallMethodEnv(); } else if(v->ivtable) { v = v->ivtable; goto again; } } default: break; } if(env) return (double)env->invocationCount(); #else (void)self; (void)type; (void)qname; (void)a; #endif return -1; }