Skip to content

Commit

Permalink
Remove static global GCNames from Function.cpp and move it to the Con…
Browse files Browse the repository at this point in the history
…text

This remove the need for locking when deleting a function.

Differential Revision: http://reviews.llvm.org/D15988

From: Mehdi Amini <mehdi.amini@apple.com>
llvm-svn: 257139
  • Loading branch information
joker-eph committed Jan 8, 2016
1 parent 7cb9d98 commit 599ebf2
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 42 deletions.
11 changes: 7 additions & 4 deletions llvm/include/llvm/IR/Function.h
Expand Up @@ -66,7 +66,8 @@ class Function : public GlobalObject, public ilist_node<Function> {
* bit 2 : HasPrologueData
* bit 3 : HasPersonalityFn
* bits 4-13 : CallingConvention
* bits 14-15 : [reserved]
* bits 14 : HasGC
* bits 15 : [reserved]
*/

/// Bits from GlobalObject::GlobalObjectSubclassData.
Expand Down Expand Up @@ -220,9 +221,11 @@ class Function : public GlobalObject, public ilist_node<Function> {

/// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm
/// to use during code generation.
bool hasGC() const;
const char *getGC() const;
void setGC(const char *Str);
bool hasGC() const {
return getSubclassDataFromValue() & (1<<14);
}
const std::string &getGC() const;
void setGC(const std::string Str);
void clearGC();

/// @brief adds the attribute to the list of attributes.
Expand Down
11 changes: 11 additions & 0 deletions llvm/include/llvm/IR/LLVMContext.h
Expand Up @@ -93,6 +93,17 @@ class LLVMContext {
/// tag registered with an LLVMContext has an unique ID.
uint32_t getOperandBundleTagID(StringRef Tag) const;


/// Define the GC for a function
void setGC(const Function &Fn, std::string GCName);

/// Return the GC for a function
const std::string &getGC(const Function &Fn);

/// Remove the GC for a function
void deleteGC(const Function &Fn);


typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,
unsigned LocCookie);

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/IR/Core.cpp
Expand Up @@ -1722,7 +1722,7 @@ void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC) {

const char *LLVMGetGC(LLVMValueRef Fn) {
Function *F = unwrap<Function>(Fn);
return F->hasGC()? F->getGC() : nullptr;
return F->hasGC()? F->getGC().c_str() : nullptr;
}

void LLVMSetGC(LLVMValueRef Fn, const char *GC) {
Expand Down
44 changes: 9 additions & 35 deletions llvm/lib/IR/Function.cpp
Expand Up @@ -366,47 +366,21 @@ void Function::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
setAttributes(PAL);
}

// Maintain the GC name for each function in an on-the-side table. This saves
// allocating an additional word in Function for programs which do not use GC
// (i.e., most programs) at the cost of increased overhead for clients which do
// use GC.
static DenseMap<const Function*,PooledStringPtr> *GCNames;
static StringPool *GCNamePool;
static ManagedStatic<sys::SmartRWMutex<true> > GCLock;

bool Function::hasGC() const {
sys::SmartScopedReader<true> Reader(*GCLock);
return GCNames && GCNames->count(this);
}

const char *Function::getGC() const {
const std::string &Function::getGC() const {
assert(hasGC() && "Function has no collector");
sys::SmartScopedReader<true> Reader(*GCLock);
return *(*GCNames)[this];
return getContext().getGC(*this);
}

void Function::setGC(const char *Str) {
sys::SmartScopedWriter<true> Writer(*GCLock);
if (!GCNamePool)
GCNamePool = new StringPool();
if (!GCNames)
GCNames = new DenseMap<const Function*,PooledStringPtr>();
(*GCNames)[this] = GCNamePool->intern(Str);
void Function::setGC(const std::string Str) {
setValueSubclassDataBit(14, !Str.empty());
getContext().setGC(*this, std::move(Str));
}

void Function::clearGC() {
sys::SmartScopedWriter<true> Writer(*GCLock);
if (GCNames) {
GCNames->erase(this);
if (GCNames->empty()) {
delete GCNames;
GCNames = nullptr;
if (GCNamePool->empty()) {
delete GCNamePool;
GCNamePool = nullptr;
}
}
}
if (!hasGC())
return;
getContext().deleteGC(*this);
setValueSubclassDataBit(14, false);
}

/// Copy all additional attributes (those not needed to create a Function) from
Expand Down
16 changes: 16 additions & 0 deletions llvm/lib/IR/LLVMContext.cpp
Expand Up @@ -304,3 +304,19 @@ void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {
uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const {
return pImpl->getOperandBundleTagID(Tag);
}

void LLVMContext::setGC(const Function &Fn, std::string GCName) {
auto It = pImpl->GCNames.find(&Fn);

if (It == pImpl->GCNames.end()) {
pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName)));
return;
}
It->second = std::move(GCName);
}
const std::string &LLVMContext::getGC(const Function &Fn) {
return pImpl->GCNames[&Fn];
}
void LLVMContext::deleteGC(const Function &Fn) {
pImpl->GCNames.erase(&Fn);
}
7 changes: 7 additions & 0 deletions llvm/lib/IR/LLVMContextImpl.h
Expand Up @@ -1027,6 +1027,13 @@ class LLVMContextImpl {
void getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const;
uint32_t getOperandBundleTagID(StringRef Tag) const;

/// Maintain the GC name for each function.
///
/// This saves allocating an additional word in Function for programs which
/// do not use GC (i.e., most programs) at the cost of increased overhead for
/// clients which do use GC.
DenseMap<const Function*, std::string> GCNames;

LLVMContextImpl(LLVMContext &C);
~LLVMContextImpl();

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp
Expand Up @@ -499,7 +499,7 @@ static bool isGCSafepointPoll(Function &F) {
static bool shouldRewriteFunction(Function &F) {
// TODO: This should check the GCStrategy
if (F.hasGC()) {
const char *FunctionGCName = F.getGC();
const auto &FunctionGCName = F.getGC();
const StringRef StatepointExampleName("statepoint-example");
const StringRef CoreCLRName("coreclr");
return (StatepointExampleName == FunctionGCName) ||
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
Expand Up @@ -2558,7 +2558,7 @@ void RewriteStatepointsForGC::stripNonValidAttributesFromBody(Function &F) {
static bool shouldRewriteStatepointsIn(Function &F) {
// TODO: This should check the GCStrategy
if (F.hasGC()) {
const char *FunctionGCName = F.getGC();
const auto &FunctionGCName = F.getGC();
const StringRef StatepointExampleName("statepoint-example");
const StringRef CoreCLRName("coreclr");
return (StatepointExampleName == FunctionGCName) ||
Expand Down

0 comments on commit 599ebf2

Please sign in to comment.