/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef __avmplus_PoolObject__ #define __avmplus_PoolObject__ namespace avmplus { #ifdef VMCFG_NANOJIT class CodeMgr; #endif // This is intended to be exactly the size of a double in memory. // (We use compile-time assertions to verify this.) class GCDouble : public MMgc::GCObject { public: double value; }; #ifdef VMCFG_FLOAT // The floats actually take 8 bytes in heap - all allocations are 8-byte // aligned. So we need to add some padding here. // (We use compile-time assertions to verify GCFloat is 8 bytes.) class GCFloat : public MMgc::GCObject { public: float value; private: int32_t padding; }; // This is intended to be exactly the size of a float4_t in memory. // (We use compile-time assertions to verify this.) class GCFloat4 : public MMgc::GCObject { public: float4_t value; }; #endif // VMCFG_FLOAT // Used within ConstantStringContainer union ConstantStringData { Stringp str; const uint8_t* abcPtr; }; // Used within PoolObject. // // The macros for exact tracing fail us here: The interpretation // of each element depends on data from the pool, so we can't treat this // with GC_STRUCTURES. Instead there's a hand-written tracer. No doubt // we could concoct a mechanism to handle this case but we should only // do so if we see more instances of it. class ConstantStringContainer : public MMgc::GCTraceableObject { private: ConstantStringContainer(PoolObject* pool) : pool(pool) {} public: REALLY_INLINE static ConstantStringContainer* create(MMgc::GC* gc, size_t extra, PoolObject* pool) { return new (gc, MMgc::kExact, extra) ConstantStringContainer(pool); } virtual bool gcTrace(MMgc::GC* gc, size_t cursor); PoolObject* const pool; // The real length is max(1,pool->constantStringCount). ConstantStringData data[1]; }; /** * The PoolObject class is a container for the pool of resources * decoded from an ABC file: the constant pool, the methods * defined in the ABC, the classes defined in the ABC, and so on. */ class GC_CPP_EXACT(PoolObject, MMgc::GCFinalizedObject) { friend class AbcParser; friend class ConstantStringContainer; friend class DomainMgr; PoolObject(AvmCore* core, ScriptBuffer& sb, const uint8_t* startpos, ApiVersion apiVersion); public: static PoolObject* create(AvmCore* core, ScriptBuffer& sb, const uint8_t* startpos, ApiVersion apiVersion); ~PoolObject(); int32_t getAPI(); ApiVersion getApiVersion(); void initPrecomputedMultinames(); const Multiname* precomputedMultiname(int32_t index); static void destroyPrecomputedMultinames(ExactStructContainer* self); // search metadata record at meta_pos for name, return true if present bool hasMetadataName(const uint8_t* meta_pos, const String* name); const uint8_t* getMetadataInfoPos(uint32_t index); /** deferred parsing */ void parseMultiname(const uint8_t *pos, Multiname& m) const; Traits* resolveTypeName(uint32_t index, const Toplevel* toplevel, bool allowVoid=false); Traits* resolveTypeName(const uint8_t*& pc, const Toplevel* toplevel, bool allowVoid=false); void resolveBindingNameNoCheck(uint32_t index, Multiname &m, const Toplevel* toplevel) const; void resolveBindingNameNoCheck(const uint8_t* &p, Multiname &m, const Toplevel* toplevel) const; Traits* resolveParameterizedType(const Toplevel* toplevel, Traits* base, Traits* type_param) const; void parseMultiname(Multiname& m, uint32_t index) const; Namespacep getNamespace(int32_t index) const; NamespaceSetp getNamespaceSet(int32_t index) const; bool hasString(int32_t index) const; Stringp getString(int32_t index) const; Atom getLegalDefaultValue(const Toplevel* toplevel, uint32_t index, CPoolKind kind, Traits* t); static bool isLegalDefaultValue(BuiltinType bt, Atom value); #ifdef VMCFG_FLOAT bool hasFloatSupport() const { return version >= 0x002F0010; /* (47<<16|16), i.e. Cyril, major v.47, minor v.16 */ } #endif bool hasExceptionSupport() const { return version != 0x002E000F; /* (46<<16|15), i.e. major v.46, minor v.15 */ } ScriptBuffer code(); bool isCodePointer(const uint8_t* pos); int32_t uniqueId() const; void setUniqueId(int32_t val); public: uint32_t classCount() const; Traits* getClassTraits(uint32_t i) const; uint32_t scriptCount() const; Traits* getScriptTraits(uint32_t i) const; uint32_t methodCount() const; MethodInfo* getMethodInfo(uint32_t i) const; #ifdef DEBUGGER DebuggerMethodInfo* getDebuggerMethodInfo(uint32_t i) const; #endif Stringp getMethodInfoName(uint32_t i); void dynamicizeStrings(); #ifdef AVMPLUS_VERBOSE bool isVerbose(uint32_t flag, MethodInfo* mi=NULL); #endif private: void setupConstantStrings(uint32_t count); // ------------------------ DATA SECTION BEGIN GC_DATA_BEGIN(PoolObject) public: AvmCore * const core; /** constants */ DataList GC_STRUCTURE(cpool_int); DataList GC_STRUCTURE(cpool_uint); GCList GC_STRUCTURE(cpool_double); #ifdef VMCFG_FLOAT GCList GC_STRUCTURE(cpool_float); // We allocate 8 bytes/float in heap. GCList GC_STRUCTURE(cpool_float4); #endif RCList GC_STRUCTURE(cpool_ns); GCList GC_STRUCTURE(cpool_ns_set); #ifdef VMCFG_HALFMOON // tables of pinned pointers for compiler-generated constants. GCList GC_STRUCTURE(cpool_const_double); RCList GC_STRUCTURE(cpool_const_string); #endif #ifndef AVMPLUS_64BIT // lists to keep int/uint atoms "sticky". // @todo this can/should go away when we convert to 64-bit Box atoms. AtomList GC_STRUCTURE(cpool_int_atoms); AtomList GC_STRUCTURE(cpool_uint_atoms); #endif DataList GC_STRUCTURE(cpool_mn_offsets); /** metadata -- ptrs into ABC, not gc-allocated */ UnmanagedPointerList GC_STRUCTURE(metadata_infos); /** domain */ GCMember GC_POINTER(domain); /** # of elements in metadata array */ uint32_t metadataCount; /** # of elements in cpool array */ uint32_t constantCount; uint32_t constantIntCount; uint32_t constantUIntCount; uint32_t constantDoubleCount; #ifdef VMCFG_FLOAT uint32_t constantFloatCount; uint32_t constantFloat4Count; #endif uint32_t constantStringCount; uint32_t constantNsCount; uint32_t constantNsSetCount; private: GCMember > GC_POINTER(precompNames); // a GCFinalizedObject public: #ifdef VMCFG_NANOJIT CodeMgr* codeMgr; // points to unmanaged memory and so, not traced #endif private: int32_t version; // "loaded" Traits/Scripts are the Traits/ScriptEnvs that are actually // defined in this Domain. "cached" Traits/Scripts are the ones that // actually should be used for a given name lookup; the cached versions // take precedence over the loaded ones (on a freeze-on-first-use basis) // to ensure that the types associated with a name can't change as new // Domains are loaded. See DomainMgr for more info. GCMember GC_POINTER(m_loadedTraits); GCMember GC_POINTER(m_cachedTraits); GCMember GC_POINTER(m_loadedScripts); GCMember GC_POINTER(m_cachedScripts); GCMember GC_POINTER(_code); const uint8_t * const _abcStart; // start of static ABC string data const uint8_t * _abcStringStart; // points behind end of ABC string data - see AbcParser.cpp const uint8_t * _abcStringEnd; GCMember GC_POINTER(_abcStrings); // The length is constantStringCount GCList GC_STRUCTURE(_classes); GCList GC_STRUCTURE(_scripts); GCList GC_STRUCTURE(_methods); #ifdef DEBUGGER GCList GC_STRUCTURE(_method_dmi); #endif // Only allocated & populated if core->config.methodName is true. // Indexed by MethodInfo::_method_id, if the value is positive, it's an index into cpool_string; // if negative, an index into cpool_mn. // Always safe because those indices are limited to 30 bits. DataList GC_STRUCTURE(_method_name_indices); ApiVersion const _apiVersion; int32_t _uniqueId; // _uniqueId + mi->method_id() produces a unique id for methods public: #ifdef AVMPLUS_VERBOSE uint32_t verbose_vb; #endif // @todo, privatize & make into bitfield (requires API churn) bool isBuiltin; // true if this pool is baked into the player. used to control whether callees will set their context. #ifdef VMCFG_AOT const AOTInfo* aotInfo; // points to non-gc memory MMgc::GCRoot *aotRoot; #endif GC_DATA_END(PoolObject) // ------------------------ DATA SECTION END }; } #endif /* __avmplus_PoolObject__ */