Commit ba389a2e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Reduce unnecessary string memsets

Particularly for string slicing, where we would
always memset the string data to zero, and then
immediately memcpy it.
parent b44f8a5b
...@@ -57,13 +57,10 @@ BoxedString* EmptyString; ...@@ -57,13 +57,10 @@ BoxedString* EmptyString;
BoxedString* characters[UCHAR_MAX + 1]; BoxedString* characters[UCHAR_MAX + 1];
BoxedString::BoxedString(const char* s, size_t n) : interned_state(SSTATE_NOT_INTERNED) { BoxedString::BoxedString(const char* s, size_t n) : interned_state(SSTATE_NOT_INTERNED) {
assert(s);
RELEASE_ASSERT(n != llvm::StringRef::npos, ""); RELEASE_ASSERT(n != llvm::StringRef::npos, "");
if (s) { memmove(data(), s, n);
memmove(data(), s, n); data()[n] = 0;
data()[n] = 0;
} else {
memset(data(), 0, n + 1);
}
} }
BoxedString::BoxedString(llvm::StringRef lhs, llvm::StringRef rhs) : interned_state(SSTATE_NOT_INTERNED) { BoxedString::BoxedString(llvm::StringRef lhs, llvm::StringRef rhs) : interned_state(SSTATE_NOT_INTERNED) {
...@@ -85,6 +82,13 @@ BoxedString::BoxedString(size_t n, char c) : interned_state(SSTATE_NOT_INTERNED) ...@@ -85,6 +82,13 @@ BoxedString::BoxedString(size_t n, char c) : interned_state(SSTATE_NOT_INTERNED)
data()[n] = 0; data()[n] = 0;
} }
BoxedString::BoxedString(size_t n) : interned_state(SSTATE_NOT_INTERNED) {
RELEASE_ASSERT(n != llvm::StringRef::npos, "");
// Note: no memset. add the null-terminator for good measure though
// (CPython does the same thing).
data()[n] = 0;
}
extern "C" char PyString_GetItem(PyObject* op, ssize_t n) noexcept { extern "C" char PyString_GetItem(PyObject* op, ssize_t n) noexcept {
RELEASE_ASSERT(PyString_Check(op), ""); RELEASE_ASSERT(PyString_Check(op), "");
return static_cast<const BoxedString*>(op)->s()[n]; return static_cast<const BoxedString*>(op)->s()[n];
...@@ -1577,11 +1581,12 @@ Box* _strSlice(BoxedString* self, i64 start, i64 stop, i64 step, i64 length) { ...@@ -1577,11 +1581,12 @@ Box* _strSlice(BoxedString* self, i64 start, i64 stop, i64 step, i64 length) {
assert(start < s.size()); assert(start < s.size());
assert(-1 <= stop); assert(-1 <= stop);
} }
assert(length >= 0);
if (length == 0) if (length == 0)
return EmptyString; return EmptyString;
BoxedString* bs = new (length) BoxedString(nullptr, length); BoxedString* bs = BoxedString::createUninitializedString(length);
copySlice(bs->data(), s.data(), start, step, length); copySlice(bs->data(), s.data(), start, step, length);
return bs; return bs;
} }
...@@ -2307,17 +2312,9 @@ extern "C" int PyString_AsStringAndSize(register PyObject* obj, register char** ...@@ -2307,17 +2312,9 @@ extern "C" int PyString_AsStringAndSize(register PyObject* obj, register char**
return 0; return 0;
} }
BoxedString* createUninitializedString(ssize_t n) {
return new (n) BoxedString(n, 0);
}
char* getWriteableStringContents(BoxedString* s) {
return s->data();
}
extern "C" PyObject* PyString_FromStringAndSize(const char* s, ssize_t n) noexcept { extern "C" PyObject* PyString_FromStringAndSize(const char* s, ssize_t n) noexcept {
if (s == NULL) if (s == NULL)
return createUninitializedString(n); return BoxedString::createUninitializedString(n);
return boxString(llvm::StringRef(s, n)); return boxString(llvm::StringRef(s, n));
} }
...@@ -2334,7 +2331,7 @@ extern "C" char* PyString_AsString(PyObject* o) noexcept { ...@@ -2334,7 +2331,7 @@ extern "C" char* PyString_AsString(PyObject* o) noexcept {
return string_getbuffer(o); return string_getbuffer(o);
BoxedString* s = static_cast<BoxedString*>(o); BoxedString* s = static_cast<BoxedString*>(o);
return getWriteableStringContents(s); return s->getWriteableStringContents();
} }
extern "C" Py_ssize_t PyString_Size(PyObject* op) noexcept { extern "C" Py_ssize_t PyString_Size(PyObject* op) noexcept {
......
...@@ -120,13 +120,6 @@ BoxedString* boxStringTwine(const llvm::Twine& s); ...@@ -120,13 +120,6 @@ BoxedString* boxStringTwine(const llvm::Twine& s);
extern "C" Box* decodeUTF8StringPtr(llvm::StringRef s); extern "C" Box* decodeUTF8StringPtr(llvm::StringRef s);
// creates an uninitialized string of length n; useful for directly constructing into the string and avoiding copies:
BoxedString* createUninitializedString(ssize_t n);
// Gets a writeable pointer to the contents of a string.
// Is only meant to be used with something just created from createUninitializedString(), though
// in theory it might work in more cases.
char* getWriteableStringContents(BoxedString* s);
extern "C" inline void listAppendInternal(Box* self, Box* v) __attribute__((visibility("default"))); extern "C" inline void listAppendInternal(Box* self, Box* v) __attribute__((visibility("default")));
extern "C" void listAppendArrayInternal(Box* self, Box** v, int nelts); extern "C" void listAppendArrayInternal(Box* self, Box** v, int nelts);
extern "C" Box* boxCLFunction(CLFunction* f, BoxedClosure* closure, Box* globals, extern "C" Box* boxCLFunction(CLFunction* f, BoxedClosure* closure, Box* globals,
...@@ -480,9 +473,20 @@ public: ...@@ -480,9 +473,20 @@ public:
explicit BoxedString(llvm::StringRef s) __attribute__((visibility("default"))); explicit BoxedString(llvm::StringRef s) __attribute__((visibility("default")));
explicit BoxedString(llvm::StringRef lhs, llvm::StringRef rhs) __attribute__((visibility("default"))); explicit BoxedString(llvm::StringRef lhs, llvm::StringRef rhs) __attribute__((visibility("default")));
// creates an uninitialized string of length n; useful for directly constructing into the string and avoiding
// copies:
static BoxedString* createUninitializedString(ssize_t n) { return new (n) BoxedString(n); }
// Gets a writeable pointer to the contents of a string.
// Is only meant to be used with something just created from createUninitializedString(), though
// in theory it might work in more cases.
char* getWriteableStringContents() { return s_data; }
private: private:
void* operator new(size_t size) = delete; void* operator new(size_t size) = delete;
BoxedString(size_t n); // non-initializing constructor
char s_data[0]; char s_data[0];
friend void setupRuntime(); friend void setupRuntime();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment