Do copying with the AttachLiteral constructors.

And, remove the IsLiteral string kind.  This removes the hazard of
creating a string whose data is freed before the string.  Callsites
passing in a literal should use StaticString.  Everything else
can use CopyString or AttachString.
Esse commit está contido em:
Edwin Smith
2013-04-24 14:56:35 -07:00
commit de Sara Golemon
commit 410a105184
3 arquivos alterados com 10 adições e 71 exclusões
+3 -27
Ver Arquivo
@@ -166,25 +166,6 @@ Array StringData::GetConstants() {
return a;
}
void StringData::initLiteral(const char* data) {
return initLiteral(data, strlen(data));
}
void StringData::initLiteral(const char* data, int len) {
if (uint32_t(len) > MaxSize) {
throw InvalidArgumentException("len > 2^31-2", len);
}
// Do not copy literals, this StringData can have a shorter lifetime than
// the literal, and the client can count on this->data() giving back
// the literal ptr with the longer lifetime. Sketchy!
m_hash = 0;
_count = 0;
m_len = len;
m_cdata = data;
m_big.cap = len | IsLiteral;
assert(checkSane());
}
void StringData::enlist() {
assert(isShared());
SweepNode& head = MemoryManager::TheMemoryManager()->m_strings;
@@ -403,7 +384,7 @@ void StringData::append(const char *s, int len) {
// TODO: t1122987: in any of the cases below where we need a bigger buffer,
// we can probably assume we're in a concat-loop and pick a good buffer
// size to avoid O(N^2) copying cost.
if (isShared() || isLiteral()) {
if (isShared()) {
// buffer is immutable, don't modify it.
StringSlice r = slice();
char* newdata = smart_concat(r.ptr, r.len, s, len);
@@ -533,12 +514,8 @@ StringData *StringData::copy(bool sharedMemory /* = false */) const {
// which will be freed at the end of the request, and so must be
// copied.
return new StringData(data(), size(), CopyMalloc);
} else {
if (isLiteral()) {
return NEW(StringData)(data(), size(), AttachLiteral);
}
return NEW(StringData)(data(), size(), CopyString);
}
return NEW(StringData)(data(), size(), CopyString);
}
MutableSlice StringData::escalate(uint32_t cap) {
@@ -568,8 +545,7 @@ StringData *StringData::Escalate(StringData *in) {
void StringData::dump() const {
StringSlice s = slice();
printf("StringData(%d) (%s%s%s%d): [", _count,
isLiteral() ? "literal " : "",
printf("StringData(%d) (%s%s%d): [", _count,
isShared() ? "shared " : "",
isStatic() ? "static " : "",
s.len);
+7 -27
Ver Arquivo
@@ -50,12 +50,6 @@ struct Slice {
typedef Slice<const char> StringSlice;
typedef Slice<char> MutableSlice;
// const char* points to a string which must remain valid for the lifetime
// of the StringData. It is fragile to rely on StringData.data() returning
// the same pointer after construction -- this invariant will probably be
// deprecated to enable copying of small strings.
enum AttachLiteralMode { AttachLiteral };
// Aggressively copy small strings and free the passed-in buffer immediately;
// otherwise keep the buffer for long strings, and free it when the string
// is mutated or released.
@@ -64,7 +58,7 @@ enum AttachStringMode { AttachString };
// const char* points to client-owned memory, StringData will copy it
// at construct-time using smart_malloc. This is only ok when the StringData
// itself was smart-allocated.
enum CopyStringMode { CopyString };
enum CopyStringMode { CopyString, AttachLiteral = CopyString };
// reserve space for buffer that will be filled in by client.
enum ReserveStringMode { ReserveString };
@@ -89,7 +83,7 @@ enum CopyMallocMode { CopyMalloc };
* big: m_data:8, _count:4, m_len:4, m_hash:4,
* junk[12], node:16, shared:8, cap:8
*
* If the format is IsLiteral or IsShared, we always use the "big" layout.
* If the format is IsShared, we always use the "big" layout.
* resemblences to fbstring are not accidental.
*/
class StringData {
@@ -99,10 +93,9 @@ class StringData {
enum Format {
IsSmall = 0, // short str overlaps m_big
IsLiteral = 0x1000000000000000, // literal string
IsShared = 0x2000000000000000, // shared memory string
IsMalloc = 0x3000000000000000, // m_big.data is malloc'd
IsSmart = 0x4000000000000000, // m_big.data is smart_malloc'd
IsShared = 0x1000000000000000, // shared memory string
IsMalloc = 0x2000000000000000, // m_big.data is malloc'd
IsSmart = 0x3000000000000000, // m_big.data is smart_malloc'd
IsMask = 0xF000000000000000
};
@@ -155,10 +148,7 @@ class StringData {
* is actually only for SmartAllocator to pre-allocate the objects.
*/
explicit StringData(const char* data) {
initLiteral(data);
}
StringData(const char *data, AttachLiteralMode) {
initLiteral(data);
initCopy(data);
}
StringData(const char *data, AttachStringMode) {
initAttach(data);
@@ -166,10 +156,6 @@ class StringData {
StringData(const char *data, CopyStringMode) {
initCopy(data);
}
StringData(const char *data, int len, AttachLiteralMode) {
initLiteral(data, len);
}
StringData(const char* data, int len, AttachStringMode) {
initAttach(data, len);
}
@@ -263,13 +249,9 @@ public:
return StringSlice(m_data, m_len);
}
bool empty() const { return size() == 0;}
bool isLiteral() const { return format() == IsLiteral; }
bool isShared() const { return format() == IsShared; }
bool isSmall() const { return format() == IsSmall; }
bool isImmutable() const {
Format f = format();
return f == IsLiteral || f == IsShared || isStatic();
}
bool isImmutable() const { return isShared() || isStatic(); }
DataType isNumericWithVal(int64_t &lval, double &dval, int allow_errors) const;
bool isNumeric() const;
bool isInteger() const;
@@ -407,10 +389,8 @@ public:
/**
* Helpers.
*/
void initLiteral(const char* data);
void initAttach(const char* data);
void initCopy(const char* data);
void initLiteral(const char* data, int len);
void initAttach(const char* data, int len);
void initCopy(const char* data, int len);
void initMalloc(const char* data, int len);
-17
Ver Arquivo
@@ -148,13 +148,6 @@ public:
m_px = NEW(StringData)(s.data(), s.size(), CopyString);
m_px->setRefCount(1);
}
// attach to null terminated string literal
String(const char *s, AttachLiteralMode mode) {
if (s) {
m_px = NEW(StringData)(s, mode);
m_px->setRefCount(1);
}
}
// attach to null terminated malloc'ed string, maybe free it now.
String(const char *s, AttachStringMode mode) {
if (s) {
@@ -169,13 +162,6 @@ public:
m_px->setRefCount(1);
}
}
// attach to binary string literal
String(const char *s, int length, AttachLiteralMode mode) {
if (s) {
m_px = NEW(StringData)(s, length, mode);
m_px->setRefCount(1);
}
}
// attach to binary malloc'ed string
String(const char *s, int length, AttachStringMode mode) {
if (s) {
@@ -261,9 +247,6 @@ public:
bool isValidVariableName() const {
return m_px ? m_px->isValidVariableName() : false;
}
bool isLiteral() const {
return m_px ? m_px->isLiteral() : true;
}
/**
* Take a sub-string from start with specified length. Note, read