Files
avmplus/core/DictionaryGlue.cpp
dmcallis 65a0592776 Initial source code drop
Source code drop for the Actionscript virtual machine in the Adobe
Flash Player for December 2013
2013-12-02 16:04:04 -08:00

188 lines
5.5 KiB
C++

/* -*- 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/. */
#include "avmplus.h"
using namespace MMgc;
namespace avmplus
{
DictionaryClass::DictionaryClass(VTable *vtable)
: ClassClosure(vtable)
{
createVanillaPrototype();
vtable->traits->itraits->set_isDictionary();
}
DictionaryObject::DictionaryObject(VTable *vtable, ScriptObject *delegate)
: ScriptObject(vtable, delegate)
{
GCAssert(vtable->traits->isDictionary());
}
void DictionaryObject::gcTraceHook_DictionaryObject(MMgc::GC *gc)
{
// This code was ripped out of ScriptObject::getTableNoInit
union {
uint8_t* p;
HeapHashtable** hht;
};
p = (uint8_t*)this + vtable->traits->getHashtableOffset();
gc->TraceLocation(hht);
}
HeapHashtable* DictionaryObject::getHeapHashtable() const
{
uint32_t const htoffset = vtable->traits->getHashtableOffset();
HeapHashtable** const p = (HeapHashtable**)(uintptr_t(this) + htoffset);
HeapHashtable* ht = *p;
if (ht == NULL)
{
MMgc::GC* gc = this->gc();
// if we are lazy-initing here, it means our ctor was never called:
// so, just assume weakKeys = false.
ht = HeapHashtable::create(gc);
WB(gc, this, p, ht);
#ifdef DEBUGGER
if (getSampler() && ht)
{
getSampler()->addDependentObject(this, ht->get_ht());
}
#endif
}
AvmAssert(ht != NULL);
return ht;
}
void DictionaryObject::init(bool weakKeys)
{
GCAssert(vtable->traits->isDictionary());
MMgc::GC* gc = this->gc();
HeapHashtable* ht = weakKeys ? WeakKeyHashtable::create(gc) : HeapHashtable::create(gc);
//store pointer of newly created hashtable, encapsulated with writebarrier,
//at the hashtable offset address of the corresponding traits
union {
uint8_t* p;
HeapHashtable** hht;
};
p = (uint8_t*)this + vtable->traits->getHashtableOffset();
WB(gc, this, hht, ht);
}
Atom FASTCALL DictionaryObject::getKeyFromObject(Atom key) const
{
AvmAssert(AvmCore::isObject(key));
ScriptObject* obj = AvmCore::atomToScriptObject(key);
AvmAssert(Traits::getBuiltinType(obj->traits()) != BUILTIN_qName);
AvmAssert(MMgc::GC::Size(obj) >= sizeof(ScriptObject));
(void)obj;
// This commented-out code probably pertains to Bugzilla 507699:
// "Dictionary key of Xml type are not matching."
//
// FIXME: this doesn't work, need to convert back to an XMLObject
// on the way out or intern XMLObject's somehow
//if(AvmCore::isXML(key))
// key = AvmCore::genericObjectToAtom(AvmCore::atomToXML(key));
return key;
}
Atom DictionaryObject::getAtomProperty(Atom key) const
{
if (AvmCore::isObject(key))
{
return getHeapHashtable()->get(getKeyFromObject(key));
}
return ScriptObject::getAtomProperty(key);
}
bool DictionaryObject::hasAtomProperty(Atom key) const
{
if (AvmCore::isObject(key))
{
return getHeapHashtable()->contains(getKeyFromObject(key));
}
return ScriptObject::hasAtomProperty(key);
}
bool DictionaryObject::deleteAtomProperty(Atom key)
{
if (AvmCore::isObject(key))
{
getHeapHashtable()->remove(getKeyFromObject(key));
return true;
}
return ScriptObject::deleteAtomProperty(key);
}
void DictionaryObject::setAtomProperty(Atom key, Atom value)
{
if (AvmCore::isObject(key))
{
getHeapHashtable()->add(getKeyFromObject(key), value);
return;
}
ScriptObject::setAtomProperty(key, value);
}
Atom DictionaryObject::nextName(int index)
{
AvmAssert(index > 0);
HeapHashtable* hht = getHeapHashtable();
Atom m = hht->keyAt(index);
Atom k = AvmCore::isNullOrUndefined(m) ? nullStringAtom : m;
if (AvmCore::isGenericObject(k) && hht->weakKeys())
{
GCWeakRef* ref = (GCWeakRef*)AvmCore::atomToGenericObject(k);
union {
GCObject* key_o;
ScriptObject* key;
};
key_o = ref->get();
if (key)
{
AvmAssert(key->traits() != NULL);
return key->atom();
}
return undefinedAtom;
}
return k;
}
Atom DictionaryObject::nextValue(int index)
{
AvmAssert(index > 0);
HeapHashtable* hht = getHeapHashtable();
Atom m = hht->keyAt(index);
if (AvmCore::isNullOrUndefined(m))
return nullStringAtom;
return hht->valueAt(index);
}
int DictionaryObject::nextNameIndex(int index)
{
AvmAssert(index >= 0);
// hht could be null if you break in debugger in a subclasses constructor before super
// has been called -- let's do it in all builds, it's better than crashing.
HeapHashtable* hht = getHeapHashtable();
return hht ? hht->next(index) : 0;
}
}