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; }
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; }