Commit ef2d7ba1 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #713 from kmod/perf3

optimize regex handling
parents baad8901 5bd967f2
...@@ -1768,6 +1768,9 @@ state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string, ...@@ -1768,6 +1768,9 @@ state_init(SRE_STATE* state, PatternObject* pattern, PyObject* string,
if (!ptr) if (!ptr)
return NULL; return NULL;
// Pyston change:
assert(charsize == 1 || charsize == sizeof(Py_UNICODE));
/* adjust boundaries */ /* adjust boundaries */
if (start < 0) if (start < 0)
start = 0; start = 0;
...@@ -1813,8 +1816,15 @@ state_fini(SRE_STATE* state) ...@@ -1813,8 +1816,15 @@ state_fini(SRE_STATE* state)
} }
/* calculate offset from start of string */ /* calculate offset from start of string */
// Pyston change: this division is expensive
/*
#define STATE_OFFSET(state, member)\ #define STATE_OFFSET(state, member)\
(((char*)(member) - (char*)(state)->beginning) / (state)->charsize) (((char*)(member) - (char*)(state)->beginning) / (state)->charsize)
*/
#define STATE_OFFSET(state, member) \
((state)->charsize == 1 ? \
(((char*)(member) - (char*)(state)->beginning)) : \
(((char*)(member) - (char*)(state)->beginning) / sizeof(Py_UNICODE)))
LOCAL(PyObject*) LOCAL(PyObject*)
state_getslice(SRE_STATE* state, Py_ssize_t index, PyObject* string, int empty) state_getslice(SRE_STATE* state, Py_ssize_t index, PyObject* string, int empty)
......
...@@ -1441,14 +1441,55 @@ extern "C" PyObject* PySequence_GetItem(PyObject* o, Py_ssize_t i) noexcept { ...@@ -1441,14 +1441,55 @@ extern "C" PyObject* PySequence_GetItem(PyObject* o, Py_ssize_t i) noexcept {
} }
} }
extern "C" PyObject* PySequence_GetSlice(PyObject* o, Py_ssize_t i1, Py_ssize_t i2) noexcept { PyObject* _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop) {
try { PyObject* start, *end, *slice;
// Not sure if this is really the same: start = PyInt_FromSsize_t(istart);
return getitem(o, createSlice(boxInt(i1), boxInt(i2), None)); if (!start)
} catch (ExcInfo e) { return NULL;
fatalOrError(PyExc_NotImplementedError, "unimplemented"); end = PyInt_FromSsize_t(istop);
return nullptr; if (!end) {
Py_DECREF(start);
return NULL;
} }
slice = PySlice_New(start, end, NULL);
Py_DECREF(start);
Py_DECREF(end);
return slice;
}
extern "C" PyObject* PySequence_GetSlice(PyObject* s, Py_ssize_t i1, Py_ssize_t i2) noexcept {
PySequenceMethods* m;
PyMappingMethods* mp;
if (!s)
return null_error();
m = s->cls->tp_as_sequence;
if (m && m->sq_slice) {
if (i1 < 0 || i2 < 0) {
if (m->sq_length) {
Py_ssize_t l = (*m->sq_length)(s);
if (l < 0)
return NULL;
if (i1 < 0)
i1 += l;
if (i2 < 0)
i2 += l;
}
}
return m->sq_slice(s, i1, i2);
} else if ((mp = s->cls->tp_as_mapping) && mp->mp_subscript) {
PyObject* res;
PyObject* slice = _PySlice_FromIndices(i1, i2);
if (!slice)
return NULL;
res = mp->mp_subscript(s, slice);
Py_DECREF(slice);
return res;
}
return type_error("'%.200s' object is unsliceable", s);
} }
extern "C" int PySequence_SetItem(PyObject* o, Py_ssize_t i, PyObject* v) noexcept { extern "C" int PySequence_SetItem(PyObject* o, Py_ssize_t i, PyObject* v) noexcept {
......
...@@ -1112,12 +1112,14 @@ static int slot_sq_ass_slice(PyObject* self, Py_ssize_t i, Py_ssize_t j, PyObjec ...@@ -1112,12 +1112,14 @@ static int slot_sq_ass_slice(PyObject* self, Py_ssize_t i, Py_ssize_t j, PyObjec
// Copied from CPython: // Copied from CPython:
#define SLOT0(FUNCNAME, OPSTR) \ #define SLOT0(FUNCNAME, OPSTR) \
static PyObject* FUNCNAME(PyObject* self) noexcept { \ static PyObject* FUNCNAME(PyObject* self) noexcept { \
STAT_TIMER(t0, "us_timer_" #FUNCNAME, SLOT_AVOIDABILITY(self)); \
static PyObject* cache_str; \ static PyObject* cache_str; \
return call_method(self, OPSTR, &cache_str, "()"); \ return call_method(self, OPSTR, &cache_str, "()"); \
} }
#define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \ #define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \
/* Pyston change: static */ PyObject* FUNCNAME(PyObject* self, ARG1TYPE arg1) noexcept { \ /* Pyston change: static */ PyObject* FUNCNAME(PyObject* self, ARG1TYPE arg1) noexcept { \
STAT_TIMER(t0, "us_timer_" #FUNCNAME, SLOT_AVOIDABILITY(self)); \
static PyObject* cache_str; \ static PyObject* cache_str; \
return call_method(self, OPSTR, &cache_str, "(" ARGCODES ")", arg1); \ return call_method(self, OPSTR, &cache_str, "(" ARGCODES ")", arg1); \
} }
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "runtime/generator.h" #include "runtime/generator.h"
#include "runtime/import.h" #include "runtime/import.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/inline/list.h"
#include "runtime/long.h" #include "runtime/long.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/set.h" #include "runtime/set.h"
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "codegen/memmgr.h" #include "codegen/memmgr.h"
#include "codegen/type_recording.h" #include "codegen/type_recording.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "runtime/inline/list.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/set.h" #include "runtime/set.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "runtime/generator.h" #include "runtime/generator.h"
#include "runtime/import.h" #include "runtime/import.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/inline/list.h"
#include "runtime/int.h" #include "runtime/int.h"
#include "runtime/long.h" #include "runtime/long.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
......
...@@ -685,7 +685,7 @@ GCAllocation* LargeArena::allocationFrom(void* ptr) { ...@@ -685,7 +685,7 @@ GCAllocation* LargeArena::allocationFrom(void* ptr) {
void LargeArena::prepareForCollection() { void LargeArena::prepareForCollection() {
for (LargeObj* lo = head; lo; lo = lo->next) { for (LargeObj* lo = head; lo; lo = lo->next) {
lookup.push_back(ObjLookupCache(lo, &lo->data[0], lo->size)); lookup.push_back(ObjLookupCache(&lo->data[0], lo->size));
} }
std::sort(lookup.begin(), lookup.end(), std::sort(lookup.begin(), lookup.end(),
[](const ObjLookupCache& lo1, const ObjLookupCache& lo2) { return lo1.data < lo2.data; }); [](const ObjLookupCache& lo1, const ObjLookupCache& lo2) { return lo1.data < lo2.data; });
...@@ -896,7 +896,7 @@ GCAllocation* HugeArena::allocationFrom(void* ptr) { ...@@ -896,7 +896,7 @@ GCAllocation* HugeArena::allocationFrom(void* ptr) {
void HugeArena::prepareForCollection() { void HugeArena::prepareForCollection() {
for (HugeObj* lo = head; lo; lo = lo->next) { for (HugeObj* lo = head; lo; lo = lo->next) {
lookup.push_back(ObjLookupCache(lo, &lo->data[0], lo->size)); lookup.push_back(ObjLookupCache(&lo->data[0], lo->size));
} }
std::sort(lookup.begin(), lookup.end(), std::sort(lookup.begin(), lookup.end(),
[](const ObjLookupCache& lo1, const ObjLookupCache& lo2) { return lo1.data < lo2.data; }); [](const ObjLookupCache& lo1, const ObjLookupCache& lo2) { return lo1.data < lo2.data; });
......
...@@ -365,11 +365,10 @@ private: ...@@ -365,11 +365,10 @@ private:
}; };
struct ObjLookupCache { struct ObjLookupCache {
void* objptr;
void* data; void* data;
size_t size; size_t size;
ObjLookupCache(void* objptr, void* data, size_t size) : objptr(objptr), data(data), size(size) {} ObjLookupCache(void* data, size_t size) : data(data), size(size) {}
}; };
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "runtime/file.h" #include "runtime/file.h"
#include "runtime/ics.h" #include "runtime/ics.h"
#include "runtime/import.h" #include "runtime/import.h"
#include "runtime/inline/list.h"
#include "runtime/inline/xrange.h" #include "runtime/inline/xrange.h"
#include "runtime/iterobject.h" #include "runtime/iterobject.h"
#include "runtime/list.h" #include "runtime/list.h"
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/file.h" #include "runtime/file.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/inline/list.h"
#include "runtime/int.h" #include "runtime/int.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/inline/list.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "codegen/parser.h" #include "codegen/parser.h"
#include "codegen/unwinding.h" #include "codegen/unwinding.h"
#include "core/ast.h" #include "core/ast.h"
#include "runtime/inline/list.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
namespace pyston { namespace pyston {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "runtime/generator.h" #include "runtime/generator.h"
#include "runtime/import.h" #include "runtime/import.h"
#include "runtime/inline/boxing.h" #include "runtime/inline/boxing.h"
#include "runtime/inline/list.h"
#include "runtime/int.h" #include "runtime/int.h"
#include "runtime/list.h" #include "runtime/list.h"
#include "runtime/long.h" #include "runtime/long.h"
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include "runtime/inline/list.h"
#include <cstring> #include <cstring>
#include "runtime/list.h" #include "runtime/list.h"
...@@ -111,38 +113,6 @@ void BoxedList::shrink() { ...@@ -111,38 +113,6 @@ void BoxedList::shrink() {
} }
} }
// TODO the inliner doesn't want to inline these; is there any point to having them in the inline section?
void BoxedList::ensure(int space) {
if (size + space > capacity) {
if (capacity == 0) {
const int INITIAL_CAPACITY = 8;
int initial = std::max(INITIAL_CAPACITY, space);
elts = new (initial) GCdArray();
capacity = initial;
} else {
int new_capacity = std::max(capacity * 2, size + space);
elts = GCdArray::realloc(elts, new_capacity);
capacity = new_capacity;
}
}
assert(capacity >= size + space);
}
// TODO the inliner doesn't want to inline these; is there any point to having them in the inline section?
extern "C" void listAppendInternal(Box* s, Box* v) {
// Lock must be held!
assert(isSubclass(s->cls, list_cls));
BoxedList* self = static_cast<BoxedList*>(s);
assert(self->size <= self->capacity);
self->ensure(1);
assert(self->size < self->capacity);
self->elts->elts[self->size] = v;
self->size++;
}
extern "C" void listAppendArrayInternal(Box* s, Box** v, int nelts) { extern "C" void listAppendArrayInternal(Box* s, Box** v, int nelts) {
// Lock must be held! // Lock must be held!
......
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_INLINE_LIST_H
#define PYSTON_RUNTIME_INLINE_LIST_H
#include "runtime/list.h"
#include "runtime/objmodel.h"
namespace pyston {
// TODO the inliner doesn't want to inline these; is there any point to having them in the inline section?
inline void BoxedList::grow(int min_free) {
if (capacity == 0) {
const int INITIAL_CAPACITY = 8;
int initial = std::max(INITIAL_CAPACITY, min_free);
elts = new (initial) GCdArray();
capacity = initial;
} else {
int new_capacity = std::max(capacity * 2, size + min_free);
elts = GCdArray::realloc(elts, new_capacity);
capacity = new_capacity;
}
}
inline void BoxedList::ensure(int min_free) {
if (unlikely(size + min_free > capacity)) {
grow(min_free);
}
assert(capacity >= size + min_free);
}
// TODO the inliner doesn't want to inline these; is there any point to having them in the inline section?
extern "C" inline void listAppendInternal(Box* s, Box* v) {
// Lock must be held!
assert(isSubclass(s->cls, list_cls));
BoxedList* self = static_cast<BoxedList*>(s);
assert(self->size <= self->capacity);
self->ensure(1);
assert(self->size < self->capacity);
self->elts->elts[self->size] = v;
self->size++;
}
}
#endif
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "gc/roots.h" #include "gc/roots.h"
#include "runtime/inline/list.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "runtime/util.h" #include "runtime/util.h"
...@@ -33,8 +34,9 @@ ...@@ -33,8 +34,9 @@
namespace pyston { namespace pyston {
extern "C" int PyList_Append(PyObject* op, PyObject* newitem) noexcept { extern "C" int PyList_Append(PyObject* op, PyObject* newitem) noexcept {
RELEASE_ASSERT(PyList_Check(op), "");
try { try {
listAppend(op, newitem); listAppendInternal(op, newitem);
} catch (ExcInfo e) { } catch (ExcInfo e) {
abort(); abort();
} }
...@@ -131,6 +133,10 @@ extern "C" Box* listLen(BoxedList* self) { ...@@ -131,6 +133,10 @@ extern "C" Box* listLen(BoxedList* self) {
return boxInt(self->size); return boxInt(self->size);
} }
static Py_ssize_t list_length(Box* self) noexcept {
return static_cast<BoxedList*>(self)->size;
}
Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step, i64 length) { Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step, i64 length) {
// printf("%ld %ld %ld\n", start, stop, step); // printf("%ld %ld %ld\n", start, stop, step);
assert(step != 0); assert(step != 0);
...@@ -151,6 +157,38 @@ Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step, i64 length) { ...@@ -151,6 +157,38 @@ Box* _listSlice(BoxedList* self, i64 start, i64 stop, i64 step, i64 length) {
return rtn; return rtn;
} }
static Box* list_slice(Box* o, Py_ssize_t ilow, Py_ssize_t ihigh) noexcept {
BoxedList* a = static_cast<BoxedList*>(o);
PyObject** src, **dest;
Py_ssize_t i, len;
if (ilow < 0)
ilow = 0;
else if (ilow > Py_SIZE(a))
ilow = Py_SIZE(a);
if (ihigh < ilow)
ihigh = ilow;
else if (ihigh > Py_SIZE(a))
ihigh = Py_SIZE(a);
len = ihigh - ilow;
BoxedList* np = new BoxedList();
np->ensure(len);
if (len) {
src = a->elts->elts + ilow;
dest = np->elts->elts;
for (i = 0; i < len; i++) {
PyObject* v = src[i];
Py_INCREF(v);
dest[i] = v;
}
}
np->size = len;
return (PyObject*)np;
}
extern "C" Box* listGetitemUnboxed(BoxedList* self, int64_t n) { extern "C" Box* listGetitemUnboxed(BoxedList* self, int64_t n) {
LOCK_REGION(self->lock.asRead()); LOCK_REGION(self->lock.asRead());
...@@ -1141,6 +1179,9 @@ void setupList() { ...@@ -1141,6 +1179,9 @@ void setupList() {
list_cls->giveAttr("__hash__", None); list_cls->giveAttr("__hash__", None);
list_cls->freeze(); list_cls->freeze();
list_cls->tp_as_sequence->sq_slice = list_slice;
list_cls->tp_as_sequence->sq_length = list_length;
CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1); CLFunction* hasnext = boxRTFunction((void*)listiterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL); addRTFunction(hasnext, (void*)listiterHasnext, BOXED_BOOL);
list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); list_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
......
...@@ -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,15 +1581,38 @@ Box* _strSlice(BoxedString* self, i64 start, i64 stop, i64 step, i64 length) { ...@@ -1577,15 +1581,38 @@ 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;
} }
static Box* str_slice(Box* o, Py_ssize_t i, Py_ssize_t j) {
BoxedString* a = static_cast<BoxedString*>(o);
if (i < 0)
i = 0;
if (j < 0)
j = 0; /* Avoid signed/unsigned bug in next line */
if (j > Py_SIZE(a))
j = Py_SIZE(a);
if (i == 0 && j == Py_SIZE(a) && PyString_CheckExact(a)) {
/* It's the same as a */
Py_INCREF(a);
return (PyObject*)a;
}
if (j < i)
j = i;
return PyString_FromStringAndSize(a->data() + i, j - i);
}
static Py_ssize_t str_length(Box* a) {
return Py_SIZE(a);
}
Box* strIsAlpha(BoxedString* self) { Box* strIsAlpha(BoxedString* self) {
assert(PyString_Check(self)); assert(PyString_Check(self));
...@@ -2307,17 +2334,9 @@ extern "C" int PyString_AsStringAndSize(register PyObject* obj, register char** ...@@ -2307,17 +2334,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 +2353,7 @@ extern "C" char* PyString_AsString(PyObject* o) noexcept { ...@@ -2334,7 +2353,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 {
...@@ -2748,6 +2767,9 @@ void setupStr() { ...@@ -2748,6 +2767,9 @@ void setupStr() {
add_operators(str_cls); add_operators(str_cls);
str_cls->freeze(); str_cls->freeze();
str_cls->tp_as_sequence->sq_slice = str_slice;
str_cls->tp_as_sequence->sq_length = str_length;
basestring_cls->giveAttr("__doc__", basestring_cls->giveAttr("__doc__",
boxString("Type basestring cannot be instantiated; it is the base for str and unicode.")); boxString("Type basestring cannot be instantiated; it is the base for str and unicode."));
basestring_cls->giveAttr("__new__", basestring_cls->giveAttr("__new__",
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "core/stats.h" #include "core/stats.h"
#include "core/types.h" #include "core/types.h"
#include "gc/collector.h" #include "gc/collector.h"
#include "runtime/inline/list.h"
#include "runtime/list.h" #include "runtime/list.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -1674,6 +1674,8 @@ extern "C" int PySlice_GetIndicesEx(PySliceObject* _r, Py_ssize_t length, Py_ssi ...@@ -1674,6 +1674,8 @@ extern "C" int PySlice_GetIndicesEx(PySliceObject* _r, Py_ssize_t length, Py_ssi
if ((*step < 0 && *stop >= *start) || (*step > 0 && *start >= *stop)) { if ((*step < 0 && *stop >= *start) || (*step > 0 && *start >= *stop)) {
*slicelength = 0; *slicelength = 0;
} else if (*step == 1) { // Pyston change: added this branch to make the common step==1 case avoid the div:
*slicelength = (*stop - *start - 1) + 1;
} else if (*step < 0) { } else if (*step < 0) {
*slicelength = (*stop - *start + 1) / (*step) + 1; *slicelength = (*stop - *start + 1) / (*step) + 1;
} else { } else {
......
...@@ -120,14 +120,7 @@ BoxedString* boxStringTwine(const llvm::Twine& s); ...@@ -120,14 +120,7 @@ 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: extern "C" inline void listAppendInternal(Box* self, Box* v) __attribute__((visibility("default")));
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" void listAppendInternal(Box* self, Box* v);
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,
std::initializer_list<Box*> defaults) noexcept; std::initializer_list<Box*> defaults) noexcept;
...@@ -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();
...@@ -549,6 +553,9 @@ public: ...@@ -549,6 +553,9 @@ public:
}; };
class BoxedList : public Box { class BoxedList : public Box {
private:
void grow(int min_free);
public: public:
int64_t size, capacity; int64_t size, capacity;
GCdArray* elts; GCdArray* elts;
...@@ -557,7 +564,7 @@ public: ...@@ -557,7 +564,7 @@ public:
BoxedList() __attribute__((visibility("default"))) : size(0), capacity(0) {} BoxedList() __attribute__((visibility("default"))) : size(0), capacity(0) {}
void ensure(int space); void ensure(int min_free);
void shrink(); void shrink();
static const int INITIAL_CAPACITY; static const int INITIAL_CAPACITY;
......
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