void InternalClass::removeMember(Object *object, Identifier *id)
{
    InternalClass *oldClass = object->internalClass;
    uint propIdx = oldClass->propertyTable.lookup(id);
    Q_ASSERT(propIdx < oldClass->size);

    Transition t = { { id } , -1 };
    QHash<Transition, InternalClass *>::const_iterator tit = object->internalClass->transitions.constFind(t);

    if (tit != object->internalClass->transitions.constEnd()) {
        object->internalClass = tit.value();
    } else {
        // create a new class and add it to the tree
        InternalClass *newClass = oldClass->engine->emptyClass->changeVTable(oldClass->vtable);
        newClass = newClass->changePrototype(oldClass->prototype);
        for (uint i = 0; i < oldClass->size; ++i) {
            if (i == propIdx)
                continue;
            if (!oldClass->propertyData.at(i).isEmpty())
                newClass = newClass->addMember(oldClass->nameMap.at(i), oldClass->propertyData.at(i));
        }
        object->internalClass = newClass;
    }

    // remove the entry in memberdata
    memmove(object->memberData.data() + propIdx, object->memberData.data() + propIdx + 1, (object->internalClass->size - propIdx)*sizeof(Value));

    oldClass->transitions.insert(t, object->internalClass);
}
InternalClass *InternalClass::changeVTable(const ManagedVTable *vt)
{
    if (vtable == vt)
        return this;

    Transition t;
    t.vtable = vt;
    t.flags = Transition::VTableChange;

    QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
    if (tit != transitions.constEnd())
        return tit.value();

    // create a new class and add it to the tree
    InternalClass *newClass;
    if (this == engine->emptyClass) {
        newClass = engine->newClass(*this);
        newClass->vtable = vt;
    } else {
        newClass = engine->emptyClass->changeVTable(vt);
        newClass = newClass->changePrototype(prototype);
        for (uint i = 0; i < size; ++i) {
            if (!propertyData.at(i).isEmpty())
                newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
        }
    }

    transitions.insert(t, newClass);
    return newClass;
}
InternalClass *InternalClass::create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto)
{
    InternalClass *c = engine->emptyClass->changeVTable(vtable);
    if (!proto)
        return c;
    return c->changePrototype(proto);
}
InternalClass *InternalClass::changeMember(String *string, PropertyAttributes data, uint *index)
{
    data.resolve();
    uint idx = find(string);
    Q_ASSERT(idx != UINT_MAX);

    if (index)
        *index = idx;

    if (data == propertyData.at(idx))
        return this;

    Transition t = { { string->identifier }, (int)data.flags() };
    QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
    if (tit != transitions.constEnd())
        return tit.value();

    // create a new class and add it to the tree
    InternalClass *newClass = engine->emptyClass->changeVTable(vtable);
    newClass = newClass->changePrototype(prototype);
    for (uint i = 0; i < size; ++i) {
        if (i == idx) {
            newClass = newClass->addMember(nameMap.at(i), data);
        } else if (!propertyData.at(i).isEmpty()) {
            newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
        }
    }

    transitions.insert(t, newClass);
    return newClass;
}
示例#5
0
void Object::setLookup(Managed *m, Lookup *l, const Value &value)
{
    Scope scope(static_cast<Object *>(m)->engine());
    ScopedObject o(scope, static_cast<Object *>(m));
    ScopedString name(scope, scope.engine->current->compilationUnit->runtimeStrings[l->nameIndex]);

    InternalClass *c = o->internalClass();
    uint idx = c->find(name);
    if (!o->isArrayObject() || idx != Heap::ArrayObject::LengthPropertyIndex) {
        if (idx != UINT_MAX && o->internalClass()->propertyData[idx].isData() && o->internalClass()->propertyData[idx].isWritable()) {
            l->classList[0] = o->internalClass();
            l->index = idx;
            l->setter = idx < o->d()->vtable()->nInlineProperties ? Lookup::setter0Inline : Lookup::setter0;
            o->setProperty(idx, value);
            return;
        }

        if (idx != UINT_MAX) {
            o->putValue(idx, value);
            return;
        }
    }

    o->put(name, value);

    if (o->internalClass() == c)
        return;
    idx = o->internalClass()->find(name);
    if (idx == UINT_MAX)
        return;
    l->classList[0] = c;
    l->classList[3] = o->internalClass();
    l->index = idx;
    if (!o->prototype()) {
        l->setter = Lookup::setterInsert0;
        return;
    }
    o = o->prototype();
    l->classList[1] = o->internalClass();
    if (!o->prototype()) {
        l->setter = Lookup::setterInsert1;
        return;
    }
    o = o->prototype();
    l->classList[2] = o->internalClass();
    if (!o->prototype()) {
        l->setter = Lookup::setterInsert2;
        return;
    }
    l->setter = Lookup::setterGeneric;
}
void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
{
    Scope scope(m->engine());
    ScopedObject o(scope, static_cast<Object *>(m));

    InternalClass *c = o->internalClass;
    uint idx = c->find(l->name);
    if (!o->isArrayObject() || idx != ArrayObject::LengthPropertyIndex) {
        if (idx != UINT_MAX && o->internalClass->propertyData[idx].isData() && o->internalClass->propertyData[idx].isWritable()) {
            l->classList[0] = o->internalClass;
            l->index = idx;
            l->setter = Lookup::setter0;
            o->memberData[idx] = *value;
            return;
        }

        if (idx != UINT_MAX) {
            o->putValue(o->propertyAt(idx), o->internalClass->propertyData[idx], value);
            return;
        }
    }

    ScopedString s(scope, l->name);
    o->put(s, value);

    if (o->internalClass == c)
        return;
    idx = o->internalClass->find(l->name);
    if (idx == UINT_MAX)
        return;
    l->classList[0] = c;
    l->classList[3] = o->internalClass;
    l->index = idx;
    if (!o->prototype()) {
        l->setter = Lookup::setterInsert0;
        return;
    }
    o = o->prototype();
    l->classList[1] = o->internalClass;
    if (!o->prototype()) {
        l->setter = Lookup::setterInsert1;
        return;
    }
    o = o->prototype();
    l->classList[2] = o->internalClass;
    if (!o->prototype()) {
        l->setter = Lookup::setterInsert2;
        return;
    }
    l->setter = Lookup::setterGeneric;
}