Exemplo n.º 1
0
    ScriptObject::ScriptObject(VTable* _vtable, ScriptObject* _delegate, int capacity) :
#ifdef DEBUGGER
        AvmPlusScriptableObject(sotObject(_vtable)),
#endif // DEBUGGER
        vtable(_vtable),
        // note that it's substantially more efficient to initialize this in the ctor
        // list vs. a later explicit call to setDelegate, as we don't have to check for marking
        // nor decrement an existing value...
        delegate(_delegate)
    {
        AvmAssert(vtable->traits->isResolved());

        // Ensure that our object is large enough to hold its extra traits data.
        AvmAssert(MMgc::GC::Size(this) >= vtable->traits->getTotalSize());

        //if capacity not specified then initialize the hashtable lazily
        if (vtable->traits->needsHashtable() && capacity)
        {
            initHashtable(capacity);
        }
    }
Exemplo n.º 2
0
Hashtable createHashtable(
    void*              self,
	char*              name, 
	long               maxItemsNum, 
	HashtableSettings  set, 
	int                setFlags)
{
	IHashtableManager _       = (IHashtableManager)self;
	IErrorLogger      elog    = (IErrorLogger)_->errorLogger;
	ISpinLockManager  slog    = (ISpinLockManager)_->spinLockHelper; 

	Hashtable         tbl;
	int               nHashLists;
	int               nSegs;
	int               segLLSize;
	uint              elemSize;
    HashSegment*      segP; 
	ulong             tblSegSize;

	/* Initialize the hash header, plus a copy of the table name.
	 * First sizeof(Hashtable) bytes are allocated for a hash table.
	 * The next strlen(Name) are allocated for the name.
	 * In this way we unate one malloc call for struct SHashtable with another 
	 * malloc for char* name.
	 */
	tbl = (Hashtable)_->memManager->alloc(sizeof(SHashtable) + strlen(name) + 1);
	memset(tbl, 0, sizeof(SHashtable));

	/* Adding one to a pointer means "produce a pointer to the object 
	 * that comes in memory right after this one," 
	 * which means that the compiler automatically scales up 
	 * whatever you're incrementing the pointer with 
	 * by the size of the object being pointed at. */
	tbl->name = (char*)(tbl + 1);
	strcpy(tbl->name, name);

    setDefaults(tbl);

	if (setFlags & HASH_FUNC)
		tbl->hashFunc = set->hashFunc;

	if (tbl->hashFunc == hashFuncStr)
		tbl->hashCmp = hashCmpFuncStr;

	if (setFlags & HASH_CMP)
		tbl->hashCmp = set->hashCmp;

    if (tbl->hashFunc == hashFuncStr)
		tbl->hashCpy = (hashCpyFunc)strcpy;

    if (setFlags & HASH_KEYCPY)
		tbl->hashCpy = set->hashCpy;

	if (setFlags & HASH_ITEM)
	{
	    tbl->keyLen = set->keyLen;
	    tbl->valLen = set->valLen;
	}

    if (setFlags & HASH_SEG)
	{
		tbl->segmSize = set->segmSize;
		tbl->segmShift = set->segmShift;
	}

    if (setFlags & HASH_LIST_SIZE)
	{
		tbl->segmsAmount = set->segmsAmount;
		tbl->maxSegmsAmount = set->maxSegmsAmount;
		tbl->hashListSize = set->hashListSize;
	}

	if (setFlags & HASH_WITHOUT_EXTENTION)
	{
        tbl->isWithoutExtention = set->isWithoutExtention;
	}

	if (setFlags & HASH_PARTITION)
	{
		Bool  isNumPowerOf2 = tbl->partNum == _->commonHelper->nextPowerOf2(tbl->partNum);

		/* First of all we need to check if the hashtable is located
		 * in the shared memory. Applying partitions to a hashtable
		 * which is located in the local memory is pointless because 
		 * no contention is applied. 
		 */
		ASSERT(elog, setFlags & HASH_SHARED_MEMORY, NULL);
        
		/* We should check if the number of partiotions is really power of 2 */
        ASSERT(elog, isNumPowerOf2, NULL);

		tbl->partNum = set->partNum; 
	}

	if (IS_TABLE_PARTITIONED(tbl))
		slog->spinLockInit(slog, &(tbl->mutex));

	nHashLists = (maxItemsNum - 1) / tbl->hashListSize + 1;
    nHashLists = _->commonHelper->nextPowerOf2(nHashLists);

	tbl->lowMask  = _->hashtableHelper->calcLowMask(nHashLists);
	tbl->highMask = _->hashtableHelper->calcHighMask(nHashLists);

	nSegs = _->hashtableHelper->calcSegmsNum(nHashLists, tbl->segmSize);

	tbl->numHashLists = nHashLists;
	tbl->segments = (AHashSegment)_->memManager->alloc(tbl->segmsAmount * sizeof(HashSegment));
    
    tblSegSize = tbl->segmSize;
	/* Allocate initial segments */
	for (segP = tbl->segments; tbl->nSegs < nSegs; tbl->nSegs++, segP++)
	{
		segLLSize = tblSegSize * sizeof(HashList);
		*segP = (HashSegment)(AHashList)_->memManager->alloc(segLLSize);
	    memset(*segP, 0, segLLSize);
	}
    
    /* Our element consists of a header and data sp that the size 
     * is sum of the header's size and data's size. 
	 * Header also includes aligned key. 
	 */
    elemSize = HASH_ELEM_SIZE(tbl);
	tbl->numItemsToAlloc = itemsNumToAlloc(elemSize);

	if (!initHashtable(_, tbl))
	{
        elog->log(LOG_ERROR,
			      ERROR_CODE_FAILED_TO_INIT_HASHTABLE,
				  "Spinlock exceeded max allowed sleep counts: %d");        

		return NULL;
	}

	if (setFlags & HASH_SEG || maxItemsNum < tbl->numItemsToAlloc)
	{
        if (!allocNewItems(_, tbl))
		{
             elog->log(LOG_ERROR,
			      ERROR_CODE_OUT_OF_MEMORY,
				  "Out of memory");        

			 return NULL;
		}

		return NULL;
	}

	return tbl;
}