bool asCModule::CanDeleteAllReferences(asCArray<asCModule*> &modules) { if( !isDiscarded ) return false; if( contextCount ) return false; modules.PushLast(this); // Check all bound functions for referenced modules for( asUINT n = 0; n < bindInformations.GetLength(); n++ ) { int funcID = bindInformations[n].importedFunction; asCModule *module = engine->GetModule(funcID); // If the module is already in the list don't check it again bool inList = false; for( asUINT m = 0; m < modules.GetLength(); m++ ) { if( modules[m] == module ) { inList = true; break; } } if( !inList ) { bool ret = module->CanDeleteAllReferences(modules); if( ret == false ) return false; } } // If no module has external references then all can be deleted return true; }
void asCBuilder::GetFunctionDescriptions(const char *name, asCArray<int> &funcs) { asUINT n; // TODO: Improve linear search for( n = 0; n < module->scriptFunctions.GetLength(); n++ ) { if( module->scriptFunctions[n]->name == name && module->scriptFunctions[n]->objectType == 0 ) funcs.PushLast(module->scriptFunctions[n]->id); } // TODO: Improve linear search for( n = 0; n < module->importedFunctions.GetLength(); n++ ) { if( module->importedFunctions[n]->name == name ) funcs.PushLast(module->importedFunctions[n]->id); } // TODO: Improve linear search for( n = 0; n < engine->scriptFunctions.GetLength(); n++ ) { if( engine->scriptFunctions[n] && engine->scriptFunctions[n]->funcType == asFUNC_SYSTEM && engine->scriptFunctions[n]->objectType == 0 && engine->scriptFunctions[n]->name == name ) { // Find the config group for the global function asCConfigGroup *group = engine->FindConfigGroupForFunction(engine->scriptFunctions[n]->id); if( !group || group->HasModuleAccess(module->name.AddressOf()) ) funcs.PushLast(engine->scriptFunctions[n]->id); } } }
void asCScriptStruct::AddUnmarkedReferences(asCArray<asCGCObject*> &unmarked) { for( asUINT n = 0; n < gc.objType->properties.GetLength(); n++ ) { asCProperty *prop = gc.objType->properties[n]; if( prop->type.IsObject() && (prop->type.GetObjectType()->flags & asOBJ_POTENTIAL_CIRCLE) ) { asCGCObject *ptr = *(asCGCObject**)(((char*)this) + prop->byteOffset); if( ptr && ptr->gc.gcCount == 0 ) unmarked.PushLast(ptr); } } }
// internal bool asCModule::AreTypesEqual(const asCDataType &a, const asCDataType &b, asCArray<sObjectTypePair> &equals) { if( !a.IsEqualExceptInterfaceType(b) ) return false; asCObjectType *ai = a.GetObjectType(); asCObjectType *bi = b.GetObjectType(); if( ai && ai->IsInterface() ) { // If the interface is in the equals list, then the pair must match the pair in the list bool found = false; unsigned int e; for( e = 0; e < equals.GetLength(); e++ ) { if( equals[e].a == ai ) { found = true; break; } } if( found ) { // Do the pairs match? if( equals[e].b != bi ) return false; } else { // Assume they are equal from now on sObjectTypePair pair = {ai, bi}; equals.PushLast(pair); } } return true; }
void asCBuilder::GetObjectMethodDescriptions(const char *name, asCObjectType *objectType, asCArray<int> &methods, bool objIsConst) { // TODO: Improve linear search if( objIsConst ) { // Only add const methods to the list for( asUINT n = 0; n < objectType->methods.GetLength(); n++ ) { if( engine->scriptFunctions[objectType->methods[n]]->name == name && engine->scriptFunctions[objectType->methods[n]]->isReadOnly ) methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id); } } else { // TODO: Prefer non-const over const for( asUINT n = 0; n < objectType->methods.GetLength(); n++ ) { if( engine->scriptFunctions[objectType->methods[n]]->name == name ) methods.PushLast(engine->scriptFunctions[objectType->methods[n]]->id); } } }
// internal bool asCModule::AreInterfacesEqual(asCObjectType *a, asCObjectType *b, asCArray<sObjectTypePair> &equals) { // An interface is considered equal to another if the following criterias apply: // // - The interface names are equal // - The number of methods is equal // - All the methods are equal // - The order of the methods is equal // - If a method returns or takes an interface by handle or reference, both interfaces must be equal // ------------ // TODO: Study the possiblity of allowing interfaces where methods are declared in different orders to // be considered equal. The compiler and VM can handle this, but it complicates the comparison of interfaces // where multiple methods take different interfaces as parameters (or return values). Example: // // interface A // { // void f(B, C); // void f(B); // void f(C); // } // // If 'void f(B)' in module A is compared against 'void f(C)' in module B, then the code will assume // interface B in module A equals interface C in module B. Thus 'void f(B, C)' in module A won't match // 'void f(C, B)' in module B. // ------------ // Are both interfaces? if( !a->IsInterface() || !b->IsInterface() ) return false; // Are the names equal? if( a->name != b->name ) return false; // Are the number of methods equal? if( a->methods.GetLength() != b->methods.GetLength() ) return false; // Keep the number of equals in the list so we can restore it later if necessary int prevEquals = (int)equals.GetLength(); // Are the methods equal to each other? bool match = true; for( unsigned int n = 0; n < a->methods.GetLength(); n++ ) { match = false; asCScriptFunction *funcA = (asCScriptFunction*)engine->GetFunctionDescriptorById(a->methods[n]); asCScriptFunction *funcB = (asCScriptFunction*)engine->GetFunctionDescriptorById(b->methods[n]); // funcB can be null if the module that created the interface has been // discarded but the type has not yet been released by the engine. if( funcB == 0 ) break; // The methods must have the same name and the same number of parameters if( funcA->name != funcB->name || funcA->parameterTypes.GetLength() != funcB->parameterTypes.GetLength() ) break; // The return types must be equal. If the return type is an interface the interfaces must match. if( !AreTypesEqual(funcA->returnType, funcB->returnType, equals) ) break; match = true; for( unsigned int p = 0; p < funcA->parameterTypes.GetLength(); p++ ) { if( !AreTypesEqual(funcA->parameterTypes[p], funcB->parameterTypes[p], equals) || funcA->inOutFlags[p] != funcB->inOutFlags[p] ) { match = false; break; } } if( !match ) break; } // For each of the new interfaces that we're assuming to be equal, we need to validate this if( match ) { for( unsigned int n = prevEquals; n < equals.GetLength(); n++ ) { if( !AreInterfacesEqual(equals[n].a, equals[n].b, equals) ) { match = false; break; } } } if( !match ) { // The interfaces doesn't match. // Restore the list of previous equals before we go on, so // the caller can continue comparing with another interface equals.SetLength(prevEquals); } return match; }