Don't allocate name strings for empty symbols
This removes unnecessary memory allocations.
BUG=angleproject:2267
TEST=angle_unittests
Change-Id: Ide575ea19ab2f8e9fc93092490f1352efa6024a3
Reviewed-on: https://chromium-review.googlesource.com/817415
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index b98c9a9..b7136f2 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -91,7 +91,8 @@
std::vector<InterfaceBlock> *infoList)
{
ASSERT(interfaceBlock);
- InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
+ ASSERT(interfaceBlock->name());
+ InterfaceBlock *namedBlock = FindVariable(*interfaceBlock->name(), infoList);
ASSERT(namedBlock);
// Set static use on the parent interface block here
@@ -569,7 +570,10 @@
{
// Structures use a NONE type that isn't exposed outside ANGLE.
variableOut->type = GL_NONE;
- variableOut->structName = structure->name().c_str();
+ if (structure->symbolType() != SymbolType::Empty)
+ {
+ variableOut->structName = structure->name()->c_str();
+ }
const TFieldList &fields = structure->fields();
@@ -578,7 +582,7 @@
// Regardless of the variable type (uniform, in/out etc.) its fields are always plain
// ShaderVariable objects.
ShaderVariable fieldVariable;
- setCommonVariableProperties(*field->type(), TName(field->name()), &fieldVariable);
+ setCommonVariableProperties(*field->type(), TName(&field->name()), &fieldVariable);
variableOut->fields.push_back(fieldVariable);
}
}
@@ -657,7 +661,7 @@
const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
ASSERT(blockType);
- interfaceBlock->name = blockType->name().c_str();
+ interfaceBlock->name = blockType->name()->c_str();
interfaceBlock->mappedName = getMappedName(TName(blockType->name()));
interfaceBlock->instanceName = instanceName.c_str();
ASSERT(!interfaceBlockType.isArrayOfArrays()); // Disallowed by GLSL ES 3.10 section 4.3.9
@@ -679,7 +683,7 @@
const TType &fieldType = *field->type();
InterfaceBlockField fieldVariable;
- setCommonVariableProperties(fieldType, TName(field->name()), &fieldVariable);
+ setCommonVariableProperties(fieldType, TName(&field->name()), &fieldVariable);
fieldVariable.isRowMajorLayout =
(fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
interfaceBlock->fields.push_back(fieldVariable);
@@ -825,7 +829,7 @@
const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
if (!namedBlock)
{
- namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
+ namedBlock = findNamedInterfaceBlock(*interfaceBlock->name());
}
ASSERT(namedBlock);
namedBlock->staticUse = true;
diff --git a/src/compiler/translator/EmulatePrecision.cpp b/src/compiler/translator/EmulatePrecision.cpp
index ba09fd7..85844d6 100644
--- a/src/compiler/translator/EmulatePrecision.cpp
+++ b/src/compiler/translator/EmulatePrecision.cpp
@@ -431,7 +431,7 @@
TString name,
TIntermSequence *arguments)
{
- TName nameObj(name);
+ TName nameObj(&name);
nameObj.setInternal(true);
TIntermAggregate *callNode =
TIntermAggregate::Create(type, EOpCallInternalRawFunction, arguments);
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 088eb43..b68724c 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -144,6 +144,10 @@
} // namespace anonymous
+TName::TName(const TString *name) : mName(name ? (*name) : ""), mIsInternal(false)
+{
+}
+
////////////////////////////////////////////////////////////////
//
// Member functions of the nodes used for building the tree.
@@ -576,7 +580,7 @@
void TFunctionSymbolInfo::setFromFunction(const TFunction &function)
{
- setName(function.name());
+ setName(*function.name());
setId(TSymbolUniqueId(function));
}
diff --git a/src/compiler/translator/IntermNode.h b/src/compiler/translator/IntermNode.h
index 7172d66..0b2436d 100644
--- a/src/compiler/translator/IntermNode.h
+++ b/src/compiler/translator/IntermNode.h
@@ -66,7 +66,7 @@
{
public:
POOL_ALLOCATOR_NEW_DELETE();
- explicit TName(const TString &name) : mName(name), mIsInternal(false) {}
+ explicit TName(const TString *name);
TName() : mName(), mIsInternal(false) {}
TName(const TName &) = default;
TName &operator=(const TName &) = default;
diff --git a/src/compiler/translator/IntermNode_util.cpp b/src/compiler/translator/IntermNode_util.cpp
index 98389da..367dc71 100644
--- a/src/compiler/translator/IntermNode_util.cpp
+++ b/src/compiler/translator/IntermNode_util.cpp
@@ -19,7 +19,7 @@
TName GetInternalFunctionName(const char *name)
{
TString nameStr(name);
- TName nameObj(nameStr);
+ TName nameObj(&nameStr);
nameObj.setInternal(true);
return nameObj;
}
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 488921d..9d02919 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -585,7 +585,7 @@
TString fieldName = field->name();
if (structure->symbolType() == SymbolType::UserDefined ||
structure->symbolType() == SymbolType::Empty)
- fieldName = hashName(TName(fieldName));
+ fieldName = hashName(TName(&fieldName));
out << fieldName;
visitChildren = false;
@@ -604,11 +604,11 @@
ASSERT(interfaceBlock->symbolType() != SymbolType::Empty);
if (interfaceBlock->symbolType() == SymbolType::UserDefined)
{
- fieldName = hashName(TName(fieldName));
+ fieldName = hashName(TName(&fieldName));
}
else
{
- ASSERT(interfaceBlock->name() == "gl_PerVertex");
+ ASSERT(*interfaceBlock->name() == "gl_PerVertex");
}
out << fieldName;
@@ -1177,7 +1177,7 @@
const TField *field = fields[i];
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
- out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
+ out << getTypeName(*field->type()) << " " << hashName(TName(&field->name()));
if (field->type()->isArray())
out << ArrayString(*field->type());
out << ";\n";
@@ -1257,7 +1257,7 @@
if (writeVariablePrecision(field->type()->getPrecision()))
out << " ";
- out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
+ out << getTypeName(*field->type()) << " " << hashName(TName(&field->name()));
if (field->type()->isArray())
out << ArrayString(*field->type());
out << ";\n";
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 70bd12f..748c788 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -341,7 +341,7 @@
{
TInterfaceBlock *interfaceBlock =
mappedStruct.blockDeclarator->getType().getInterfaceBlock();
- const TString &interfaceBlockName = interfaceBlock->name();
+ const TString &interfaceBlockName = *interfaceBlock->name();
const TName &instanceName = mappedStruct.blockDeclarator->getName();
if (mReferencedUniformBlocks.count(interfaceBlockName) == 0)
{
@@ -380,7 +380,7 @@
TType *structType = mappedStruct.field->type();
mappedStructs +=
- "static " + Decorate(structType->getStruct()->name()) + " " + mappedName;
+ "static " + Decorate(*structType->getStruct()->name()) + " " + mappedName;
if (structType->isArray())
{
@@ -890,7 +890,7 @@
if (interfaceBlock)
{
- mReferencedUniformBlocks[interfaceBlock->name()] = node;
+ mReferencedUniformBlocks[*interfaceBlock->name()] = node;
}
else
{
@@ -1238,7 +1238,7 @@
{
TInterfaceBlock *interfaceBlock = leftType.getInterfaceBlock();
TIntermSymbol *instanceArraySymbol = node->getLeft()->getAsSymbolNode();
- mReferencedUniformBlocks[interfaceBlock->name()] = instanceArraySymbol;
+ mReferencedUniformBlocks[*interfaceBlock->name()] = instanceArraySymbol;
const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0);
out << mUniformHLSL->UniformBlockInstanceString(
instanceArraySymbol->getSymbol(), arrayIndex);
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index ed51367..a2b486d 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -2445,7 +2445,7 @@
if (type.getBasicType() == EbtStruct)
{
TVariable *emptyVariable =
- new TVariable(&symbolTable, NewPoolTString(""), type, SymbolType::Empty);
+ new TVariable(&symbolTable, nullptr, type, SymbolType::Empty);
symbol = new TIntermSymbol(emptyVariable);
}
else if (IsAtomicCounter(publicType.getBasicType()))
@@ -3153,7 +3153,8 @@
const TSourceLoc &location,
bool insertParametersToSymbolTable)
{
- checkIsNotReserved(location, function.name());
+ ASSERT(function.name());
+ checkIsNotReserved(location, *function.name());
TIntermFunctionPrototype *prototype =
new TIntermFunctionPrototype(function.getReturnType(), TSymbolUniqueId(function));
@@ -3200,7 +3201,7 @@
// The parameter had no name or declaring the symbol failed - either way, add a nameless
// symbol.
TVariable *emptyVariable =
- new TVariable(&symbolTable, NewPoolTString(""), *param.type, SymbolType::Empty);
+ new TVariable(&symbolTable, nullptr, *param.type, SymbolType::Empty);
symbol = new TIntermSymbol(emptyVariable);
}
symbol->setLine(location);
@@ -3271,12 +3272,13 @@
{
ASSERT(function);
ASSERT(*function);
+ ASSERT((*function)->name());
const TSymbol *builtIn =
symbolTable.findBuiltIn((*function)->getMangledName(), getShaderVersion());
if (builtIn)
{
- error(location, "built-in functions cannot be redefined", (*function)->name().c_str());
+ error(location, "built-in functions cannot be redefined", (*function)->name()->c_str());
}
else
{
@@ -3298,7 +3300,7 @@
if ((*function)->isDefined())
{
- error(location, "function already has a body", (*function)->name().c_str());
+ error(location, "function already has a body", (*function)->name()->c_str());
}
(*function)->setDefined();
@@ -3325,6 +3327,8 @@
TFunction *prevDec =
static_cast<TFunction *>(symbolTable.find(function->getMangledName(), getShaderVersion()));
+ ASSERT(function->name() != nullptr);
+
for (size_t i = 0u; i < function->getParamCount(); ++i)
{
auto ¶m = function->getParam(i);
@@ -3332,17 +3336,17 @@
{
// ESSL 3.00.6 section 12.10.
error(location, "Function parameter type cannot be a structure definition",
- function->name().c_str());
+ function->name()->c_str());
}
}
if (getShaderVersion() >= 300 && symbolTable.hasUnmangledBuiltInForShaderVersion(
- function->name().c_str(), getShaderVersion()))
+ function->name()->c_str(), getShaderVersion()))
{
// With ESSL 3.00 and above, names of built-in functions cannot be redeclared as functions.
// Therefore overloading or redefining builtin functions is an error.
error(location, "Name of a built-in function cannot be redeclared as function",
- function->name().c_str());
+ function->name()->c_str());
}
else if (prevDec)
{
@@ -3366,12 +3370,12 @@
//
// Check for previously declared variables using the same name.
//
- TSymbol *prevSym = symbolTable.find(function->name(), getShaderVersion());
+ TSymbol *prevSym = symbolTable.find(*function->name(), getShaderVersion());
if (prevSym)
{
if (!prevSym->isFunction())
{
- error(location, "redefinition of a function", function->name().c_str());
+ error(location, "redefinition of a function", function->name()->c_str());
}
}
else
@@ -3385,7 +3389,7 @@
symbolTable.getOuterLevel()->insert(function);
// Raise error message if main function takes any parameters or return anything other than void
- if (function->name() == "main")
+ if (*function->name() == "main")
{
if (function->getParamCount() > 0)
{
@@ -3814,16 +3818,13 @@
}
// The instance variable gets created to refer to the interface block type from the AST
- // regardless of if there's an instance name. It just has an empty name if there's no instance
- // name.
- if (!instanceName)
- {
- instanceName = NewPoolTString("");
- }
+ // regardless of if there's an instance name. It's created as an empty symbol if there is no
+ // instance name.
TVariable *instanceVariable =
- new TVariable(&symbolTable, instanceName, interfaceBlockType, SymbolType::UserDefined);
+ new TVariable(&symbolTable, instanceName, interfaceBlockType,
+ instanceName ? SymbolType::UserDefined : SymbolType::Empty);
- if (instanceName->empty())
+ if (instanceVariable->symbolType() == SymbolType::Empty)
{
// define symbols for the members of the interface block
for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
@@ -3902,8 +3903,9 @@
// one to the field's struct nesting.
if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
{
+ ASSERT(field.type()->getStruct()->name() != nullptr);
std::stringstream reasonStream;
- reasonStream << "Reference of struct type " << field.type()->getStruct()->name().c_str()
+ reasonStream << "Reference of struct type " << field.type()->getStruct()->name()->c_str()
<< " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
std::string reason = reasonStream.str();
error(line, reason.c_str(), field.name().c_str());
@@ -4770,7 +4772,6 @@
SymbolType structSymbolType = SymbolType::UserDefined;
if (structName == nullptr)
{
- structName = NewPoolTString("");
structSymbolType = SymbolType::Empty;
}
TStructure *structure = new TStructure(&symbolTable, structName, fieldList, structSymbolType);
@@ -5780,10 +5781,10 @@
// It's possible for the name pointer in the TFunction to be null in case it gets parsed as
// a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
// mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
- // So accessing fnCall->getName() below is safe.
- if (fnCall->name() != "length")
+ // So accessing fnCall->name() below is safe.
+ if (*fnCall->name() != "length")
{
- error(loc, "invalid method", fnCall->name().c_str());
+ error(loc, "invalid method", fnCall->name()->c_str());
}
else if (!arguments->empty())
{
@@ -5816,18 +5817,18 @@
// hidden by a variable name or struct typename.
// If a function is found, check for one with a matching argument list.
bool builtIn;
- const TSymbol *symbol = symbolTable.find(fnCall->name(), mShaderVersion, &builtIn);
+ const TSymbol *symbol = symbolTable.find(*fnCall->name(), mShaderVersion, &builtIn);
if (symbol != nullptr && !symbol->isFunction())
{
- error(loc, "function name expected", fnCall->name().c_str());
+ error(loc, "function name expected", fnCall->name()->c_str());
}
else
{
- symbol = symbolTable.find(TFunction::GetMangledNameFromCall(fnCall->name(), *arguments),
+ symbol = symbolTable.find(TFunction::GetMangledNameFromCall(*fnCall->name(), *arguments),
mShaderVersion, &builtIn);
if (symbol == nullptr)
{
- error(loc, "no matching overloaded function found", fnCall->name().c_str());
+ error(loc, "no matching overloaded function found", fnCall->name()->c_str());
}
else
{
diff --git a/src/compiler/translator/RegenerateStructNames.cpp b/src/compiler/translator/RegenerateStructNames.cpp
index a17e5d8..32940d8 100644
--- a/src/compiler/translator/RegenerateStructNames.cpp
+++ b/src/compiler/translator/RegenerateStructNames.cpp
@@ -19,12 +19,15 @@
if (!userType)
return;
- if (userType->symbolType() == SymbolType::BuiltIn)
+ if (userType->symbolType() == SymbolType::BuiltIn ||
+ userType->symbolType() == SymbolType::Empty)
{
- // Built-in struct, do not touch it.
+ // Built-in struct or nameless struct, do not touch it.
return;
}
+ ASSERT(userType->name() != nullptr);
+
int uniqueId = userType->uniqueId().get();
ASSERT(mScopeDepth > 0);
@@ -50,14 +53,14 @@
return;
// Map {name} to _webgl_struct_{uniqueId}_{name}.
const char kPrefix[] = "_webgl_struct_";
- if (userType->name().find(kPrefix) == 0)
+ if (userType->name()->find(kPrefix) == 0)
{
// The name has already been regenerated.
return;
}
std::string id = Str(uniqueId);
TString tmp = kPrefix + TString(id.c_str());
- tmp += "_" + userType->name();
+ tmp += "_" + *userType->name();
userType->setName(tmp);
}
diff --git a/src/compiler/translator/RemoveUnreferencedVariables.cpp b/src/compiler/translator/RemoveUnreferencedVariables.cpp
index 36ed3f2..0f845cd 100644
--- a/src/compiler/translator/RemoveUnreferencedVariables.cpp
+++ b/src/compiler/translator/RemoveUnreferencedVariables.cpp
@@ -192,8 +192,8 @@
// Already an empty declaration - nothing to do.
return;
}
- TVariable *emptyVariable = new TVariable(mSymbolTable, NewPoolTString(""),
- declarator->getType(), SymbolType::Empty);
+ TVariable *emptyVariable =
+ new TVariable(mSymbolTable, nullptr, declarator->getType(), SymbolType::Empty);
queueReplacementWithParent(node, declarator, new TIntermSymbol(emptyVariable),
OriginalNode::IS_DROPPED);
return;
diff --git a/src/compiler/translator/SymbolTable.cpp b/src/compiler/translator/SymbolTable.cpp
index 04956d3..18f2f80 100644
--- a/src/compiler/translator/SymbolTable.cpp
+++ b/src/compiler/translator/SymbolTable.cpp
@@ -40,19 +40,25 @@
{
ASSERT(mSymbolType == SymbolType::BuiltIn || mExtension == TExtension::UNDEFINED);
ASSERT(mName != nullptr || mSymbolType == SymbolType::AngleInternal ||
- mSymbolType == SymbolType::NotResolved);
+ mSymbolType == SymbolType::NotResolved || mSymbolType == SymbolType::Empty);
}
-const TString &TSymbol::name() const
+const TString *TSymbol::name() const
{
- if (mName != nullptr)
+ if (mName != nullptr || mSymbolType == SymbolType::Empty)
{
- return *mName;
+ return mName;
}
ASSERT(mSymbolType == SymbolType::AngleInternal);
TInfoSinkBase symbolNameOut;
symbolNameOut << "s" << mUniqueId.get();
- return *NewPoolTString(symbolNameOut.c_str());
+ return NewPoolTString(symbolNameOut.c_str());
+}
+
+const TString &TSymbol::getMangledName() const
+{
+ ASSERT(mSymbolType != SymbolType::Empty);
+ return *name();
}
TVariable::TVariable(TSymbolTable *symbolTable,
@@ -109,6 +115,7 @@
mBlockStorage(layoutQualifier.blockStorage),
mBinding(layoutQualifier.binding)
{
+ ASSERT(name != nullptr);
}
//
@@ -138,7 +145,7 @@
const TString *TFunction::buildMangledName() const
{
- std::string newName = name().c_str();
+ std::string newName = name()->c_str();
newName += kFunctionMangledNameSeparator;
for (const auto &p : parameters)
@@ -181,7 +188,8 @@
bool TSymbolTableLevel::insertUnmangled(TFunction *function)
{
// returning true means symbol was added to the table
- tInsertResult result = level.insert(tLevelPair(function->name(), function));
+ ASSERT(function->name() != nullptr);
+ tInsertResult result = level.insert(tLevelPair(*function->name(), function));
return result.second;
}
diff --git a/src/compiler/translator/SymbolTable.h b/src/compiler/translator/SymbolTable.h
index 9827ee9..41bbc40 100644
--- a/src/compiler/translator/SymbolTable.h
+++ b/src/compiler/translator/SymbolTable.h
@@ -67,8 +67,8 @@
// don't delete name, it's from the pool
}
- const TString &name() const;
- virtual const TString &getMangledName() const { return name(); }
+ const TString *name() const;
+ virtual const TString &getMangledName() const;
virtual bool isFunction() const { return false; }
virtual bool isVariable() const { return false; }
virtual bool isStruct() const { return false; }
diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp
index 1488df7..3ca8806 100644
--- a/src/compiler/translator/Types.cpp
+++ b/src/compiler/translator/Types.cpp
@@ -475,12 +475,16 @@
{
case EbtStruct:
mangledName += "struct-";
- mangledName += mStructure->name();
+ if (mStructure->name() != nullptr)
+ {
+ mangledName += *mStructure->name();
+ }
mangledName += mStructure->mangledFieldList();
break;
case EbtInterfaceBlock:
mangledName += "iblock-";
- mangledName += mInterfaceBlock->name();
+ ASSERT(mInterfaceBlock->name() != nullptr);
+ mangledName += *mInterfaceBlock->name();
mangledName += mInterfaceBlock->mangledFieldList();
break;
default:
diff --git a/src/compiler/translator/UniformHLSL.cpp b/src/compiler/translator/UniformHLSL.cpp
index ebea83d..079c550 100644
--- a/src/compiler/translator/UniformHLSL.cpp
+++ b/src/compiler/translator/UniformHLSL.cpp
@@ -61,7 +61,8 @@
static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
{
- return DecoratePrivate(interfaceBlock.name()) + "_type";
+ ASSERT(interfaceBlock.name() != nullptr);
+ return DecoratePrivate(*interfaceBlock.name()) + "_type";
}
void OutputSamplerIndexArrayInitializer(TInfoSinkBase &out,
@@ -479,7 +480,8 @@
}
unsigned int activeRegister = mUniformBlockRegister;
- mUniformBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister;
+ ASSERT(interfaceBlock.name() != nullptr);
+ mUniformBlockRegisterMap[interfaceBlock.name()->c_str()] = activeRegister;
if (instanceName != "" && nodeType.isArray())
{
@@ -510,7 +512,8 @@
{
const TString &arrayIndexString =
(arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : "");
- const TString &blockName = interfaceBlock.name() + arrayIndexString;
+ ASSERT(interfaceBlock.name() != nullptr);
+ const TString &blockName = *interfaceBlock.name() + arrayIndexString;
TString hlsl;
hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) +
diff --git a/src/compiler/translator/UtilsHLSL.cpp b/src/compiler/translator/UtilsHLSL.cpp
index f6c7497..1569225 100644
--- a/src/compiler/translator/UtilsHLSL.cpp
+++ b/src/compiler/translator/UtilsHLSL.cpp
@@ -855,10 +855,10 @@
// translation so that we can link between shader stages.
if (structure.atGlobalScope())
{
- return Decorate(structure.name());
+ return Decorate(*structure.name());
}
- return "ss" + str(structure.uniqueId().get()) + "_" + structure.name();
+ return "ss" + str(structure.uniqueId().get()) + "_" + *structure.name();
}
TString QualifiedStructNameString(const TStructure &structure,