Traits* PoolObject::resolveParameterizedType(const Toplevel* toplevel, Traits* base, Traits* param_traits ) const { Traits* r = NULL; if( base == core->traits.vector_itraits) { // Only vector is parameterizable for now... if(!param_traits) // Vector.<*> r = core->traits.vectorobj_itraits; else if( param_traits == core->traits.int_itraits) r = core->traits.vectorint_itraits; else if (param_traits == core->traits.uint_itraits) r = core->traits.vectoruint_itraits; else if (param_traits == core->traits.number_itraits) r = core->traits.vectordouble_itraits; else { Stringp fullname = core->internString( core->concatStrings(core->newString("Vector.<"), core->concatStrings(param_traits->formatClassName(), core->newString(">")))->atom()); Multiname newname; newname.setName(fullname); newname.setNamespace(base->ns); r = getTraits(newname, toplevel); if( !r ) { r = core->traits.vectorobj_itraits->newParameterizedITraits(fullname, base->ns); core->traits.vector_itraits->pool->domain->addNamedTrait(fullname, base->ns, r); } } } return r; }
MethodEnv* ProxyObject::getMethod(Stringp name)const { //Atom atom=this->getAtomProperty(name->atom()); //if(AvmCore::isNullOrUndefined(atom)) return NULL; //return AvmCore::atomToScriptObject(atom); Multiname m; m.setName(name); m.setNamespace(m_pNamespace); Binding b = avmplus::getBinding(toplevel(), vtable, &m); if(AvmCore::bindingKind(b)!=BKIND_METHOD) return NULL; return vtable->methods[AvmCore::bindingToMethodId(b)]; }
PrecomputedMultinames::PrecomputedMultinames(MMgc::GC* gc, PoolObject* pool) : MMgc::GCRoot(gc) , nNames (0) { nNames = pool->constantMnCount; for ( uint32 i=1 ; i < nNames ; i++ ) { Multiname mn; pool->parseMultiname(mn, i); mn.IncrementRef(); multinames[i] = mn; } }
// This is always safe. We must /not/ use WBRC_NULL here, only the full WBRC functions that // take the gc and container explicitly will be safe. See bugzilla 525875. void HeapMultiname::setMultiname(MMgc::GC* gc, const void* container, const Multiname& that) { WBRC(gc, container, &name.name, that.name); bool const this_nsset = name.isNsset() != 0; bool const that_nsset = that.isNsset() != 0; if (this_nsset != that_nsset) { // gc->rc or vice versa... we have to explicitly null out // any existing value (before setting a new one) because WB/WBRC // assume any existing value is a GCObject/RCObject respectively. if (this_nsset) WB_NULL(&name.ns); // WB_NULL is safe else WBRC(gc, container, &name.ns, NULL); // DO NOT USE WBRC_NULL } if (that_nsset) { WB(gc, container, &name.nsset, that.nsset); } else { WBRC(gc, container, &name.ns, that.ns); } name.flags = that.flags; name.next_index = that.next_index; }
Traits* PoolObject::resolveTypeName(uint32 index, const Toplevel* toplevel, bool allowVoid/*=false*/) const { // only save the type name for now. verifier will resolve to traits if (index == 0) { return NULL; } // check contents is a multiname. in the cpool, and type system, kObjectType means multiname. if (index >= constantMnCount) { if (toplevel) toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(constantMnCount)); AvmAssert(!"unhandled verify error"); } Multiname m; parseMultiname(cpool_mn[index], m); Traits* t = getTraits(m, toplevel); if(m.isParameterizedType()) { Traits* param_traits = resolveTypeName(m.getTypeParameter(), toplevel); t = resolveParameterizedType(toplevel, t, param_traits); } if (!t) { #ifdef AVMPLUS_VERBOSE if (!toplevel || !toplevel->verifyErrorClass()) core->console << "class not found: " << m << " index=" << index << "\n"; #endif if (toplevel) toplevel->throwVerifyError(kClassNotFoundError, core->toErrorString(&m)); AvmAssert(!"unhandled verify error"); } if (!allowVoid && t == VOID_TYPE) { if (toplevel) toplevel->throwVerifyError(kIllegalVoidError); AvmAssert(!"unhandled verify error"); } return t; }
uint32_t SlotOffsetsAndAsserts::getSlotOffset(Traits* t, int nameId) { Multiname name; t->pool->parseMultiname(name, nameId); if (name.isNsset()) name.setNamespace(name.getNsset()->nsAt(0)); AvmAssert(!name.isNsset()); const TraitsBindings* tb = t->getTraitsBindings(); Binding b = tb->findBinding(name.getName(), name.getNamespace()); AvmAssert(AvmCore::isSlotBinding(b)); int slotId = AvmCore::bindingToSlotId(b); return tb->getSlotOffset(slotId); }
void PoolObject::resolveQName(uint32_t index, Multiname &m, const Toplevel* toplevel) const { if (index == 0 || index >= constantMnCount) { if (toplevel) toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(constantMnCount)); AvmAssert(!"unhandled verify error"); } parseMultiname(cpool_mn[index], m); if (!m.isQName()) { if (toplevel) toplevel->throwVerifyError(kCpoolEntryWrongTypeError, core->toErrorString(index)); AvmAssert(!"unhandled verify error"); } }
bool NativeInitializer::getCompiledInfo(NativeMethodInfo *info, Multiname &returnTypeName, uint32_t i) const { info->thunker = (AvmThunkNativeThunker)0; if (i < compiledMethodCount && compiledMethods[i]) { bool isNumberRetType = false; if (NUMBER_TYPE) { Multiname numberTypeName(NUMBER_TYPE->ns(), NUMBER_TYPE->name()); isNumberRetType = returnTypeName.matches(&numberTypeName); } info->thunker = isNumberRetType ? (AvmThunkNativeThunker)aotThunkerN : (AvmThunkNativeThunker)aotThunker; info->handler.function = compiledMethods[i]; return true; } else { info->handler.function = (AvmThunkNativeFunctionHandler)0; return false; } }
void PoolObject::parseMultiname(const byte *pos, Multiname& m) const { // the multiname has already been validated so we don't do // any checking here, we just fill in the Multiname object // with the information we have parsed. int index; CPoolKind kind = (CPoolKind) *(pos++); switch (kind) { case CONSTANT_Qname: case CONSTANT_QnameA: { // U16 namespace_index // U16 name_index // parse a multiname with one namespace (aka qname) index = AvmCore::readU30(pos); if (!index) m.setAnyNamespace(); else m.setNamespace(getNamespace(index)); index = AvmCore::readU30(pos); if (!index) m.setAnyName(); else m.setName(getString(index)); m.setQName(); m.setAttr(kind==CONSTANT_QnameA); break; } case CONSTANT_RTQname: case CONSTANT_RTQnameA: { // U16 name_index // parse a multiname with just a name; ns fetched at runtime index = AvmCore::readU30(pos); if (!index) m.setAnyName(); else m.setName(getString(index)); m.setQName(); m.setRtns(); m.setAttr(kind==CONSTANT_RTQnameA); break; } case CONSTANT_RTQnameL: case CONSTANT_RTQnameLA: { m.setQName(); m.setRtns(); m.setRtname(); m.setAttr(kind==CONSTANT_RTQnameLA); break; } case CONSTANT_Multiname: case CONSTANT_MultinameA: { index = AvmCore::readU30(pos); if (!index) m.setAnyName(); else m.setName(getString(index)); index = AvmCore::readU30(pos); AvmAssert(index != 0); m.setNsset(getNamespaceSet(index)); m.setAttr(kind==CONSTANT_MultinameA); break; } case CONSTANT_MultinameL: case CONSTANT_MultinameLA: { m.setRtname(); index = AvmCore::readU30(pos); AvmAssert(index != 0); m.setNsset(getNamespaceSet(index)); m.setAttr(kind==CONSTANT_MultinameLA); break; } case CONSTANT_TypeName: { index = AvmCore::readU30(pos); Atom a = cpool_mn[index]; parseMultiname(atomToPos(a), m); index = AvmCore::readU30(pos); AvmAssert(index==1); m.setTypeParameter(AvmCore::readU30(pos)); break; } default: AvmAssert(false); } return; }
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; }