Accelerate costly Value functions by storing results.

This commit is contained in:
Axel Naumann 2015-04-04 23:44:38 +02:00 committed by sftnight
parent 474d518615
commit ca9ac1961f
2 changed files with 49 additions and 40 deletions

View File

@ -51,16 +51,6 @@ namespace cling {
/// \brief The actual value.
Storage m_Storage;
/// \brief The value's type, stored as opaque void* to reduce
/// dependencies.
void* m_Type;
///\brief Interpreter, produced the value.
///
///(Size without this is 24, this member makes it 32)
///
Interpreter* m_Interpreter;
enum EStorageType {
kSignedIntegerOrEnumerationType,
kUnsignedIntegerOrEnumerationType,
@ -68,11 +58,27 @@ namespace cling {
kFloatType,
kLongDoubleType,
kPointerType,
kManagedAllocation,
kUnsupportedType
};
/// \brief Which part in m_Storage is active.
EStorageType m_StorageType;
/// \brief The value's type, stored as opaque void* to reduce
/// dependencies.
void* m_Type;
///\brief Interpreter that produced the value.
///
Interpreter* m_Interpreter;
/// \brief Retrieve the underlying, canonical, desugared, unqualified type.
EStorageType getStorageType() const;
EStorageType getStorageType() const { return m_StorageType; }
/// \brief Determine the underlying, canonical, desugared, unqualified type:
/// the element of Storage to be used.
EStorageType determineStorageType(clang::QualType QT) const;
/// \brief Allocate storage as needed by the type.
void ManagedAllocate();
@ -103,6 +109,7 @@ namespace cling {
case kLongDoubleType:
return (T) V.getAs<long double>();
case kPointerType:
case kManagedAllocation:
return (T) (size_t) V.getAs<void*>();
case kUnsupportedType:
V.AssertOnUnsupportedTypeCast();
@ -115,19 +122,19 @@ namespace cling {
struct CastFwd<T*> {
static T* cast(const Value& V) {
EStorageType storageType = V.getStorageType();
switch (storageType) {
case kPointerType:
if (storageType == kPointerType
|| storageType == kManagedAllocation)
return (T*) (size_t) V.getAs<void*>();
default:
V.AssertOnUnsupportedTypeCast(); break;
}
V.AssertOnUnsupportedTypeCast();
return 0;
}
};
public:
/// \brief Default constructor, creates a value that IsInvalid().
Value(): m_Type(0), m_Interpreter(0) {}
Value():
m_StorageType(kUnsupportedType), m_Type(nullptr),
m_Interpreter(nullptr) {}
/// \brief Copy a value.
Value(const Value& other);
/// \brief Move a value.
@ -144,13 +151,14 @@ namespace cling {
clang::QualType getType() const;
clang::ASTContext& getASTContext() const;
Interpreter* getInterpreter() { return m_Interpreter; }
const Interpreter* getInterpreter() const { return m_Interpreter; }
Interpreter* getInterpreter() const { return m_Interpreter; }
/// \brief Whether this type needs managed heap, i.e. the storage provided
/// by the m_Storage member is insufficient, or a non-trivial destructor
/// must be called.
bool needsManagedAllocation() const;
bool needsManagedAllocation() const {
return getStorageType() == kManagedAllocation;
}
/// \brief Determine whether the Value has been set.
//
@ -165,8 +173,7 @@ namespace cling {
//
/// Determine whether the Value is set and not void.
/// Only in this case can getAs() or simplisticCastAs() be called.
bool hasValue() const {
return isValid() && !isVoid(); }
bool hasValue() const { return isValid() && !isVoid(); }
/// \brief Get a reference to the value without type checking.
/// T *must* correspond to type. Else use simplisticCastAs()!

View File

@ -143,21 +143,23 @@ namespace {
namespace cling {
Value::Value(const Value& other):
m_Storage(other.m_Storage), m_Type(other.m_Type),
m_Interpreter(other.m_Interpreter) {
if (needsManagedAllocation())
m_Storage(other.m_Storage), m_StorageType(other.m_StorageType),
m_Type(other.m_Type), m_Interpreter(other.m_Interpreter) {
if (other.needsManagedAllocation())
AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Retain();
}
Value::Value(Value&& other):
m_Storage(other.m_Storage), m_Type(other.m_Type),
m_Interpreter(other.m_Interpreter) {
m_Storage(other.m_Storage), m_StorageType(other.m_StorageType),
m_Type(other.m_Type), m_Interpreter(other.m_Interpreter) {
// Invalidate other so it will not release.
other.m_Type = 0;
other.m_StorageType = kUnsupportedType;
}
Value::Value(clang::QualType clangTy, Interpreter& Interp):
m_Type(clangTy.getAsOpaquePtr()), m_Interpreter(&Interp) {
m_Type(clangTy.getAsOpaquePtr()),
m_StorageType(determineStorageType(clangTy)),
m_Interpreter(&Interp) {
if (needsManagedAllocation())
ManagedAllocate();
}
@ -170,6 +172,7 @@ namespace cling {
// Retain new one.
m_Type = other.m_Type;
m_Storage = other.m_Storage;
m_StorageType = other.m_StorageType;
m_Interpreter = other.m_Interpreter;
if (needsManagedAllocation())
AllocatedValue::getFromPayload(m_Storage.m_Ptr)->Retain();
@ -184,9 +187,10 @@ namespace cling {
// Move new one.
m_Type = other.m_Type;
m_Storage = other.m_Storage;
m_StorageType = other.m_StorageType;
m_Interpreter = other.m_Interpreter;
// Invalidate other so it will not release.
other.m_Type = 0;
other.m_StorageType = kUnsupportedType;
return *this;
}
@ -225,8 +229,8 @@ namespace cling {
return 1;
}
Value::EStorageType Value::getStorageType() const {
const clang::Type* desugCanon = getType()->getUnqualifiedDesugaredType();
Value::EStorageType Value::determineStorageType(clang::QualType QT) const {
const clang::Type* desugCanon = QT->getUnqualifiedDesugaredType();
desugCanon = desugCanon->getCanonicalTypeUnqualified()->getTypePtr()
->getUnqualifiedDesugaredType();
if (desugCanon->isSignedIntegerOrEnumerationType())
@ -242,19 +246,17 @@ namespace cling {
else if (BT->getKind() == clang::BuiltinType::LongDouble)
return kLongDoubleType;
} else if (desugCanon->isPointerType() || desugCanon->isObjectType()
|| desugCanon->isReferenceType())
|| desugCanon->isReferenceType()) {
if (desugCanon->isRecordType() || desugCanon->isConstantArrayType()
|| desugCanon->isMemberPointerType())
return kManagedAllocation;
return kPointerType;
}
return kUnsupportedType;
}
bool Value::needsManagedAllocation() const {
if (!isValid()) return false;
const clang::Type* UnqDes = getType()->getUnqualifiedDesugaredType();
return UnqDes->isRecordType() || UnqDes->isConstantArrayType()
|| UnqDes->isMemberPointerType();
}
void Value::ManagedAllocate() {
assert(needsManagedAllocation() && "Does not need managed allocation");
void* dtorFunc = 0;
clang::QualType DtorType = getType();
// For arrays we destruct the elements.