asherkin@263: /* vim: set ts=4 sw=4 tw=99 et: asherkin@263: * asherkin@263: * Copyright (C) 2012 David Anderson asherkin@263: * asherkin@263: * This file is part of SourcePawn. asherkin@263: * asherkin@263: * SourcePawn is free software: you can redistribute it and/or modify it under asherkin@263: * the terms of the GNU General Public License as published by the Free asherkin@263: * Software Foundation, either version 3 of the License, or (at your option) asherkin@263: * any later version. asherkin@263: * asherkin@263: * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY asherkin@263: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS asherkin@263: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. asherkin@263: * asherkin@263: * You should have received a copy of the GNU General Public License along with asherkin@263: * SourcePawn. If not, see http://www.gnu.org/licenses/. asherkin@263: */ asherkin@263: #include asherkin@263: #include "Types.h" asherkin@263: #include "TypeManager.h" asherkin@263: #include "Zone.h" asherkin@263: #include "Strings.h" asherkin@263: #include "Spaces-inl.h" asherkin@263: #include "Heap-inl.h" asherkin@263: asherkin@263: using namespace ke; asherkin@263: asherkin@263: asherkin@263: TypeManager::TypeManager(Zone *zone) asherkin@263: : zone_(zone), asherkin@263: qualTable_(ZoneAllocatorPolicy()) asherkin@263: { asherkin@263: } asherkin@263: asherkin@263: bool asherkin@263: TypeManager::initialize() asherkin@263: { asherkin@263: voidType_ = Type::NewVoid(zone_); asherkin@263: if (!voidType_) asherkin@263: return false; asherkin@263: asherkin@263: uncheckedType_ = Type::NewUnchecked(zone_); asherkin@263: if (!uncheckedType_) asherkin@263: return false; asherkin@263: asherkin@263: stringType_ = Type::NewString(zone_); asherkin@263: if (!stringType_) asherkin@263: return false; asherkin@263: asherkin@263: importableType_ = Type::NewImportable(zone_); asherkin@263: if (!importableType_) asherkin@263: return false; asherkin@263: asherkin@263: typeType_ = Type::NewType(zone_); asherkin@263: if (!typeType_) asherkin@263: return false; asherkin@263: asherkin@263: if ((primitiveTypes_[PrimitiveType_Int32] = Type::NewPrimitive(zone_, PrimitiveType_Int32)) == NULL) asherkin@263: return false; asherkin@263: if ((primitiveTypes_[PrimitiveType_Float] = Type::NewPrimitive(zone_, PrimitiveType_Float)) == NULL) asherkin@263: return false; asherkin@263: if ((primitiveTypes_[PrimitiveType_Native] = Type::NewPrimitive(zone_, PrimitiveType_Native)) == NULL) asherkin@263: return false; asherkin@263: if ((primitiveTypes_[PrimitiveType_Char] = Type::NewPrimitive(zone_, PrimitiveType_Char)) == NULL) asherkin@263: return false; asherkin@263: if ((primitiveTypes_[PrimitiveType_Bool] = Type::NewPrimitive(zone_, PrimitiveType_Bool)) == NULL) asherkin@263: return false; asherkin@263: asherkin@263: Local type(zone_); asherkin@263: for (unsigned i = 0; i < PrimitiveTypes_Total; i++) { asherkin@263: type = primitiveTypes_[i]; asherkin@263: if ((referenceTypes_[i] = ReferenceType::New(zone_, type)) == NULL) asherkin@263: return false; asherkin@263: } asherkin@263: asherkin@263: if (!qualTable_.init(32)) asherkin@263: return false; asherkin@263: asherkin@263: return true; asherkin@263: } asherkin@263: asherkin@263: ArrayType * asherkin@263: TypeManager::newArray(Handle contained, int elements) asherkin@263: { asherkin@263: // :TODO: cache this. asherkin@263: return ArrayType::New(zone_, contained, elements); asherkin@263: } asherkin@263: asherkin@263: ArrayType * asherkin@263: TypeManager::newExternalArray(Handle contained) asherkin@263: { asherkin@263: return ArrayType::NewExternal(zone_, contained); asherkin@263: } asherkin@263: asherkin@263: ReferenceType * asherkin@263: TypeManager::getReference(Handle type, bool isConst) asherkin@263: { asherkin@263: if (!isConst && type->isPrimitive()) asherkin@263: return referenceTypes_[type->primitive()]; asherkin@263: asherkin@263: // :TODO: cache this. asherkin@263: return ReferenceType::New(zone_, type); asherkin@263: } asherkin@263: asherkin@263: EnumType * asherkin@263: TypeManager::newEnum(Handle name) asherkin@263: { asherkin@263: return EnumType::New(zone_, name); asherkin@263: } asherkin@263: asherkin@263: Type * asherkin@263: TypeManager::qualify(Handle argType, TypeQualifiers quals) asherkin@263: { asherkin@263: Local type(zone_, argType->unqualified()); asherkin@263: asherkin@263: if (!quals) asherkin@263: return type; asherkin@263: asherkin@263: LookupKey key(type, quals); asherkin@263: asherkin@263: // We can't use findForAdd because a GC could rehash the table. asherkin@263: TypeHashTable::Result r = qualTable_.find(key); asherkin@263: if (r.found()) asherkin@263: return *r; asherkin@263: asherkin@263: Type *quald = Type::NewQualified(zone_, quals, type); asherkin@263: if (!quald) asherkin@263: return NULL; asherkin@263: asherkin@263: // :TODO: assert-no-gc asherkin@263: TypeHashTable::Insert i = qualTable_.findForAdd(key); asherkin@263: assert(!i.found()); asherkin@263: asherkin@263: if (!qualTable_.add(i, quald)) asherkin@263: return NULL; asherkin@263: asherkin@263: return quald; asherkin@263: } asherkin@263: asherkin@263: void asherkin@263: TypeManager::accept(VirtualObjectVisitor *visitor) asherkin@263: { asherkin@263: visitor->visit(voidType_.address()); asherkin@263: visitor->visit(uncheckedType_.address()); asherkin@263: visitor->visit(stringType_.address()); asherkin@263: visitor->visit(importableType_.address()); asherkin@263: visitor->visit(typeType_.address()); asherkin@263: for (unsigned i = 0; i < PrimitiveTypes_Total; i++) { asherkin@263: visitor->visit(primitiveTypes_[i].address()); asherkin@263: visitor->visit(referenceTypes_[i].address()); asherkin@263: } asherkin@263: } asherkin@263: asherkin@263: void asherkin@263: TypeManager::sweep() asherkin@263: { asherkin@263: for (TypeHashTable::iterator i(&qualTable_); !i.empty(); i.next()) { asherkin@263: Type *obj = *i; asherkin@263: MarkBit bits = HeapChunk::GetMarkBit(obj); asherkin@263: if (HeapChunk::IsWhite(bits)) asherkin@263: i.erase(); asherkin@263: else asherkin@263: assert(HeapChunk::IsBlack(bits)); asherkin@263: } asherkin@263: qualTable_.checkDensity(); asherkin@263: }