ScriptObject* ScriptObject::getSlotObject(uint32_t slot) { Traits* traits = this->traits(); const TraitsBindingsp td = traits->getTraitsBindings(); void* p; const SlotStorageType sst = td->calcSlotAddrAndSST(slot, (void*)this, p); // based on profiling of Flex apps, it's *much* more common for the slot in this case // to have a type (vs "atom"), so check for that first... if (sst == SST_scriptobject) { return *((ScriptObject**)p); } else if (sst == SST_atom) { Atom const a = *((const Atom*)p); // don't call AvmCore::isObject(); it checks for null, which we don't care about here if (atomKind(a) == kObjectType) return (ScriptObject*)atomPtr(a); // else fall thru and return null } return NULL; }
Atom ScriptObject::getSlotAtom(uint32_t slot) { Traits* traits = this->traits(); const TraitsBindingsp td = traits->getTraitsBindings(); // repeated if-else is actually more performant than a switch statement in this case. // SST_atom is most common case, put it first void* p; const SlotStorageType sst = td->calcSlotAddrAndSST(slot, (void*)this, p); if (sst == SST_atom) { return *((const Atom*)p); } else if (sst == SST_double) { return traits->core->doubleToAtom(*((const double*)p)); } else if (sst == SST_int32) { return traits->core->intToAtom(*((const int32_t*)p)); } else if (sst == SST_uint32) { return traits->core->uintToAtom(*((const int32_t*)p)); } else if (sst == SST_bool32) { return (*((const int32_t*)p)<<3)|kBooleanType; } else if (sst == SST_string) { return (*((const Stringp*)p))->atom(); // may be null|kStringType, that's ok } else if (sst == SST_namespace) { return (*((const Namespacep*)p))->atom(); // may be null|kNamespaceType, no problemo } else // if (sst == SST_scriptobject) { AvmAssert(sst == SST_scriptobject); return (*((const ScriptObject**)p))->atom(); // may be null|kObjectType, copacetic } }
// note: coerceAndSetSlotAtom now includes a simplified and streamlined version // of Toplevel::coerce. If you modify that code, you might need to modify this code. void ScriptObject::coerceAndSetSlotAtom(uint32_t slot, Atom value) { Traits* traits = this->traits(); const TraitsBindingsp td = traits->getTraitsBindings(); void* p; const SlotStorageType sst = td->calcSlotAddrAndSST(slot, (void*)this, p); // repeated if-else is actually more performant than a switch statement in this case. // SST_atom is most common case, put it first if (sst == SST_atom) { // no call to coerce() needed, since anything will fit here... with one exception: // BUILTIN_object needs to convert undefined->null (though BUILTIN_any does not). // it's cheaper to do that here than call out to coerce(). AvmAssert(td->getSlotTraits(slot) == NULL || td->getSlotTraits(slot)->builtinType == BUILTIN_object); if (value == undefinedAtom && td->getSlotTraits(slot) != NULL) value = nullObjectAtom; WBATOM(traits->core->GetGC(), this, (Atom*)p, value); } else if (sst == SST_double) { *((double*)p) = AvmCore::number(value); } else if (sst == SST_int32) { *((int32_t*)p) = AvmCore::integer(value); } else if (sst == SST_uint32) { *((uint32_t*)p) = AvmCore::toUInt32(value); } else if (sst == SST_bool32) { *((int32_t*)p) = AvmCore::boolean(value); } else { // null/undefined -> NULL for all of these if (AvmCore::isNullOrUndefined(value)) { value = (Atom)0; // don't bother setting tag bits } else if (sst == SST_string) { value = (Atom)traits->core->string(value); // don't bother setting tag bits } else if (sst == SST_namespace) { // Namespace is final, so we don't have to do the hard work if (atomKind(value) != kNamespaceType) goto failure; } else // if (sst == SST_scriptobject) { AvmAssert(sst == SST_scriptobject); if (atomKind(value) != kObjectType || !AvmCore::atomToScriptObject(value)->traits()->subtypeof(td->getSlotTraits(slot))) goto failure; } WBRC(traits->core->GetGC(), this, p, atomPtr(value)); } return; failure: toplevel()->throwTypeError(kCheckTypeFailedError, traits->core->atomToErrorString(value), traits->core->toErrorString(td->getSlotTraits(slot))); return; }