Objective C cleanup. Removed an cache that was no longer needed and changes the code that gets the dynamic type and class name to use our new Objective C cache.

llvm-svn: 166512
This commit is contained in:
Greg Clayton 2012-10-23 22:41:19 +00:00
parent edf8e38701
commit d64dd12fcf
5 changed files with 114 additions and 255 deletions

View File

@ -349,10 +349,10 @@ public:
}
void
SetName (ConstString &type_name_const_str);
SetName (const ConstString &type_name);
void
SetName (const char *type_name_str);
SetName (const char *type_name_cstr);
void
SetTypeSP (lldb::TypeSP type_sp);

View File

@ -45,14 +45,16 @@ public:
public:
ClassDescriptor() :
m_is_kvo(eLazyBoolCalculate),
m_is_cf(eLazyBoolCalculate)
{}
ClassDescriptor (ObjCISA isa, lldb::ProcessSP process) :
m_is_kvo(eLazyBoolCalculate),
m_is_cf(eLazyBoolCalculate)
{}
m_is_kvo (eLazyBoolCalculate),
m_is_cf (eLazyBoolCalculate),
m_type_wp ()
{
}
virtual
~ClassDescriptor ()
{
}
virtual ConstString
GetClassName () = 0;
@ -118,9 +120,17 @@ public:
return false;
}
virtual
~ClassDescriptor ()
{}
lldb::TypeSP
GetType ()
{
return m_type_wp.lock();
}
void
SetType (const lldb::TypeSP &type_sp)
{
m_type_wp = type_sp;
}
protected:
bool
@ -133,6 +143,7 @@ public:
private:
LazyBool m_is_kvo;
LazyBool m_is_cf;
lldb::TypeWP m_type_wp;
};
// a convenience subclass of ClassDescriptor meant to represent invalid objects
@ -141,6 +152,10 @@ public:
public:
ClassDescriptor_Invalid() {}
virtual
~ClassDescriptor_Invalid ()
{}
virtual ConstString
GetClassName () { return ConstString(""); }
@ -164,11 +179,6 @@ public:
{
return false;
}
virtual
~ClassDescriptor_Invalid ()
{}
};
virtual ClassDescriptorSP
@ -443,10 +453,6 @@ protected:
ISAToDescriptorMap m_isa_to_descriptor_cache;
bool m_isa_to_descriptor_cache_is_up_to_date;
typedef std::map<lldb::addr_t,TypeAndOrName> ClassNameMap;
typedef ClassNameMap::iterator ClassNameIterator;
ClassNameMap m_class_name_cache;
typedef std::map<ConstString, lldb::TypeWP> CompleteClassMap;
CompleteClassMap m_complete_class_cache;

View File

@ -259,152 +259,31 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
if (CouldHaveDynamicValue (in_value))
{
// First job, pull out the address at 0 offset from the object That will be the ISA pointer.
Error error;
const addr_t object_ptr = in_value.GetPointerValue();
const addr_t isa_addr = m_process->ReadPointerFromMemory (object_ptr, error);
if (error.Fail())
return false;
address.SetRawAddress(object_ptr);
// First check the cache...
SymbolContext sc;
class_type_or_name = LookupInClassNameCache (isa_addr);
if (!class_type_or_name.IsEmpty())
ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value));
if (objc_class_sp)
{
if (class_type_or_name.GetTypeSP())
return true;
else
return false;
}
const addr_t object_ptr = in_value.GetPointerValue();
address.SetRawAddress(object_ptr);
// We don't have the object cached, so make sure the class
// address is readable, otherwise this is not a good object:
m_process->ReadPointerFromMemory (isa_addr, error);
if (error.Fail())
return false;
const char *class_name = NULL;
Address isa_address;
Target &target = m_process->GetTarget();
target.GetSectionLoadList().ResolveLoadAddress (isa_addr, isa_address);
if (isa_address.IsValid())
{
// If the ISA pointer points to one of the sections in the binary, then see if we can
// get the class name from the symbols.
SectionSP section_sp (isa_address.GetSection());
if (section_sp)
{
// If this points to a section that we know about, then this is
// some static class or nothing. See if it is in the right section
// and if its name is the right form.
ConstString section_name = section_sp->GetName();
static ConstString g_objc_class_section_name ("__objc_data");
if (section_name == g_objc_class_section_name)
{
isa_address.CalculateSymbolContext(&sc, eSymbolContextModule | eSymbolContextSymbol);
if (sc.symbol)
{
if (sc.symbol->GetType() == eSymbolTypeObjCClass)
class_name = sc.symbol->GetName().GetCString();
else if (sc.symbol->GetType() == eSymbolTypeObjCMetaClass)
{
// FIXME: Meta-classes can't have dynamic types...
return false;
}
}
}
}
}
char class_buffer[1024];
if (class_name == NULL && use_dynamic == eDynamicCanRunTarget)
{
// If the class address didn't point into the binary, or
// it points into the right section but there wasn't a symbol
// there, try to look it up by calling the class method in the target.
ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
Thread *thread_to_use = exe_ctx.GetThreadPtr();
if (thread_to_use == NULL)
thread_to_use = m_process->GetThreadList().GetSelectedThread().get();
if (thread_to_use == NULL)
return false;
if (!RunFunctionToFindClassName (object_ptr, thread_to_use, class_buffer, 1024))
return false;
class_name = class_buffer;
}
if (class_name && class_name[0])
{
class_type_or_name.SetName (class_name);
TypeList class_types;
const bool exact_match = true;
uint32_t num_matches = target.GetImages().FindTypes (sc,
class_type_or_name.GetName(),
exact_match,
UINT32_MAX,
class_types);
if (num_matches == 1)
{
class_type_or_name.SetTypeSP (class_types.GetTypeAtIndex(0));
return true;
}
ConstString class_name (objc_class_sp->GetClassName());
class_type_or_name.SetName(class_name);
TypeSP type_sp (objc_class_sp->GetType());
if (type_sp)
class_type_or_name.SetTypeSP (type_sp);
else
{
for (size_t i = 0; i < num_matches; i++)
type_sp = LookupInCompleteClassCache (class_name);
if (type_sp)
{
TypeSP this_type(class_types.GetTypeAtIndex(i));
if (this_type)
{
// Only consider "real" ObjC classes. For now this means avoiding
// the Type objects that are made up from the OBJC_CLASS_$_<NAME> symbols.
// we don't want to use them since they are empty and useless.
if (this_type->IsRealObjCClass())
{
// There can only be one type with a given name,
// so we've just found duplicate definitions, and this
// one will do as well as any other.
// We don't consider something to have a dynamic type if
// it is the same as the static type. So compare against
// the value we were handed:
clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
clang::ASTContext *this_ast_ctx = this_type->GetClangAST ();
if (in_ast_ctx != this_ast_ctx
|| !ClangASTContext::AreTypesSame (in_ast_ctx,
in_value.GetClangType(),
this_type->GetClangFullType()))
{
class_type_or_name.SetTypeSP (this_type);
}
break;
}
}
objc_class_sp->SetType (type_sp);
class_type_or_name.SetTypeSP (type_sp);
}
}
AddToClassNameCache (isa_addr, class_type_or_name);
if (class_type_or_name.GetTypeSP())
if (type_sp)
return true;
else
return false;
}
}
}
return false;
}
@ -1699,7 +1578,17 @@ AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj)
Error error;
ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
if (isa != LLDB_INVALID_ADDRESS)
{
objc_class_sp = ObjCLanguageRuntime::GetClassDescriptor (isa);
if (isa && !objc_class_sp)
{
lldb::LogSP log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
if (log)
log->Printf("0x%llx: AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%llx",
isa_pointer,
isa);
}
}
}
}
}

View File

@ -838,15 +838,15 @@ TypeAndOrName::GetName () const
}
void
TypeAndOrName::SetName (ConstString &type_name_const_str)
TypeAndOrName::SetName (const ConstString &type_name)
{
m_type_name = type_name_const_str;
m_type_name = type_name;
}
void
TypeAndOrName::SetName (const char *type_name_str)
TypeAndOrName::SetName (const char *type_name_cstr)
{
m_type_name.SetCString (type_name_str);
m_type_name.SetCString (type_name_cstr);
}
void

View File

@ -58,47 +58,6 @@ ObjCLanguageRuntime::LookupInMethodCache (lldb::addr_t class_addr, lldb::addr_t
return LLDB_INVALID_ADDRESS;
}
void
ObjCLanguageRuntime::AddToClassNameCache (lldb::addr_t class_addr, const char *name, lldb::TypeSP type_sp)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
{
log->Printf ("Caching: class 0x%llx name: %s.", class_addr, name);
}
TypeAndOrName class_type_or_name;
if (type_sp)
class_type_or_name.SetTypeSP (type_sp);
else if (name && *name != '\0')
class_type_or_name.SetName (name);
else
return;
m_class_name_cache.insert (std::pair<lldb::addr_t,TypeAndOrName> (class_addr, class_type_or_name));
}
void
ObjCLanguageRuntime::AddToClassNameCache (lldb::addr_t class_addr, const TypeAndOrName &class_type_or_name)
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
if (log)
{
log->Printf ("Caching: class 0x%llx name: %s.", class_addr, class_type_or_name.GetName().AsCString());
}
m_class_name_cache.insert (std::pair<lldb::addr_t,TypeAndOrName> (class_addr, class_type_or_name));
}
TypeAndOrName
ObjCLanguageRuntime::LookupInClassNameCache (lldb::addr_t class_addr)
{
ClassNameMap::iterator pos, end = m_class_name_cache.end();
pos = m_class_name_cache.find (class_addr);
if (pos != end)
return (*pos).second;
return TypeAndOrName ();
}
lldb::TypeSP
ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
@ -107,72 +66,77 @@ ObjCLanguageRuntime::LookupInCompleteClassCache (ConstString &name)
if (complete_class_iter != m_complete_class_cache.end())
{
TypeSP ret(complete_class_iter->second);
// Check the weak pointer to make sure the type hasn't been unloaded
TypeSP complete_type_sp (complete_class_iter->second.lock());
if (!ret)
m_complete_class_cache.erase(name);
if (complete_type_sp)
return complete_type_sp;
else
return TypeSP(complete_class_iter->second);
m_complete_class_cache.erase(name);
}
ModuleList &modules = m_process->GetTarget().GetImages();
SymbolContextList sc_list;
const size_t matching_symbols = modules.FindSymbolsWithNameAndType (name,
eSymbolTypeObjCClass,
sc_list);
modules.FindSymbolsWithNameAndType(name, eSymbolTypeObjCClass, sc_list);
if (sc_list.GetSize() == 0)
return TypeSP();
SymbolContext sc;
sc_list.GetContextAtIndex(0, sc);
ModuleSP module_sp(sc.module_sp);
if (!module_sp)
return TypeSP();
const SymbolContext null_sc;
const bool exact_match = true;
const uint32_t max_matches = UINT32_MAX;
TypeList types;
module_sp->FindTypes (null_sc,
name,
exact_match,
max_matches,
types);
if (types.GetSize() == 1)
if (matching_symbols)
{
TypeSP candidate_type = types.GetTypeAtIndex(0);
SymbolContext sc;
if (ClangASTContext::IsObjCClassType(candidate_type->GetClangForwardType()))
{
m_complete_class_cache[name] = TypeWP(candidate_type);
return candidate_type;
}
else
{
sc_list.GetContextAtIndex(0, sc);
ModuleSP module_sp(sc.module_sp);
if (!module_sp)
return TypeSP();
}
}
for (uint32_t ti = 0, te = types.GetSize();
ti < te;
++ti)
{
TypeSP candidate_type = types.GetTypeAtIndex(ti);
if (candidate_type->IsCompleteObjCClass() &&
ClangASTContext::IsObjCClassType(candidate_type->GetClangForwardType()))
const SymbolContext null_sc;
const bool exact_match = true;
const uint32_t max_matches = UINT32_MAX;
TypeList types;
const uint32_t num_types = module_sp->FindTypes (null_sc,
name,
exact_match,
max_matches,
types);
if (num_types)
{
m_complete_class_cache[name] = TypeWP(candidate_type);
return candidate_type;
TypeSP incomplete_type_sp;
uint32_t i;
for (i = 0; i < num_types; ++i)
{
TypeSP type_sp (types.GetTypeAtIndex(i));
if (ClangASTContext::IsObjCClassType(type_sp->GetClangForwardType()))
{
if (type_sp->IsCompleteObjCClass())
{
m_complete_class_cache[name] = type_sp;
return type_sp;
}
else if (!incomplete_type_sp)
incomplete_type_sp = type_sp;
}
}
// We didn't find any "real" definitions, so just use any??? Why was
// this being done? Prior to this, if there was 1 match only, then it
// would always use any objc definition, else we would only accept a
// definition if it was the real thing???? Doesn't make sense.
if (incomplete_type_sp)
{
m_complete_class_cache[name] = incomplete_type_sp;
return incomplete_type_sp;
}
}
}
return TypeSP();
}