Commit 4385b6bc authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #716 from kmod/perf2

speed calling of (some) capi code
parents e648044c caa5000a
......@@ -83,6 +83,14 @@ PyAPI_FUNC(PyObject *) PyCFunction_NewEx(PyMethodDef *, PyObject *,
#define METH_COEXIST 0x0040
/* Pyston additions: */
#define METH_O2 0x0080
#define METH_O3 (METH_O | METH_O2)
// The number of defaults:
#define METH_D1 0x0200
#define METH_D2 0x0400
#define METH_D3 (METH_D1 | METH_D2)
typedef struct PyMethodChain {
PyMethodDef *methods; /* Methods of this type */
struct PyMethodChain *link; /* NULL or base type */
......
......@@ -24,15 +24,25 @@ PyObject * _do_string_format(PyObject *self, PyObject *args, PyObject *kwargs) {
}
PyObject *
string_count(PyStringObject *self, PyObject *args)
string_count(PyStringObject *self,
PyObject *sub_obj, PyObject* obj_start, PyObject** args)
{
PyObject *sub_obj;
const char *str = PyString_AS_STRING(self), *sub;
Py_ssize_t sub_len;
Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
PyObject* obj_end = args[0];
/*
if (!stringlib_parse_args_finds("count", args, &sub_obj, &start, &end))
return NULL;
*/
if (obj_start && obj_start != Py_None)
if (!_PyEval_SliceIndex(obj_start, &start))
return 0;
if (obj_end && obj_end != Py_None)
if (!_PyEval_SliceIndex(obj_end, &end))
return 0;
if (PyString_Check(sub_obj)) {
sub = PyString_AS_STRING(sub_obj);
......
......@@ -6300,16 +6300,31 @@ Unicode string S[start:end]. Optional arguments start and end are\n\
interpreted as in slice notation.");
static PyObject *
unicode_count(PyUnicodeObject *self, PyObject *args)
unicode_count(PyUnicodeObject *self,
PyObject *subobj, PyObject* obj_start, PyObject** args)
{
PyUnicodeObject *substring;
Py_ssize_t start = 0;
Py_ssize_t end = PY_SSIZE_T_MAX;
PyObject *result;
PyObject* obj_end = args[0];
/*
if (!stringlib_parse_args_finds_unicode("count", args, &substring,
&start, &end))
return NULL;
*/
if (obj_start && obj_start != Py_None)
if (!_PyEval_SliceIndex(obj_start, &start))
return 0;
if (obj_end && obj_end != Py_None)
if (!_PyEval_SliceIndex(obj_end, &end))
return 0;
substring = (PyUnicodeObject*)PyUnicode_FromObject(subobj);
if (!substring)
return 0;
ADJUST_INDICES(start, end, self->length);
result = PyInt_FromSsize_t(
......@@ -7656,16 +7671,26 @@ prefix can also be a tuple of strings to try.");
static PyObject *
unicode_startswith(PyUnicodeObject *self,
PyObject *args)
PyObject *subobj, PyObject* obj_start, PyObject** args)
{
PyObject *subobj;
PyUnicodeObject *substring;
Py_ssize_t start = 0;
Py_ssize_t end = PY_SSIZE_T_MAX;
int result;
PyObject* obj_end = args[0];
/*
if (!stringlib_parse_args_finds("startswith", args, &subobj, &start, &end))
return NULL;
*/
if (obj_start && obj_start != Py_None)
if (!_PyEval_SliceIndex(obj_start, &start))
return 0;
if (obj_end && obj_end != Py_None)
if (!_PyEval_SliceIndex(obj_end, &end))
return 0;
if (PyTuple_Check(subobj)) {
Py_ssize_t i;
for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
......@@ -7814,7 +7839,7 @@ static PyMethodDef unicode_methods[] = {
{"capitalize", (PyCFunction) unicode_capitalize, METH_NOARGS, capitalize__doc__},
{"title", (PyCFunction) unicode_title, METH_NOARGS, title__doc__},
{"center", (PyCFunction) unicode_center, METH_VARARGS, center__doc__},
{"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__},
{"count", (PyCFunction) unicode_count, METH_O3 | METH_D2, count__doc__},
{"expandtabs", (PyCFunction) unicode_expandtabs, METH_VARARGS, expandtabs__doc__},
{"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__},
{"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__},
......@@ -7834,7 +7859,7 @@ static PyMethodDef unicode_methods[] = {
{"swapcase", (PyCFunction) unicode_swapcase, METH_NOARGS, swapcase__doc__},
{"translate", (PyCFunction) unicode_translate, METH_O, translate__doc__},
{"upper", (PyCFunction) unicode_upper, METH_NOARGS, upper__doc__},
{"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__},
{"startswith", (PyCFunction) unicode_startswith, METH_O3 | METH_D2, startswith__doc__},
{"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__},
{"islower", (PyCFunction) unicode_islower, METH_NOARGS, islower__doc__},
{"isupper", (PyCFunction) unicode_isupper, METH_NOARGS, isupper__doc__},
......
......@@ -11,7 +11,7 @@ try:
except:
pyston_loaded = False
template_source = """
template_source = u"""
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
......@@ -97,7 +97,7 @@ template_source = """
"""
elapsed = 0
for i in xrange(5000):
for i in xrange(10000):
# print i
lexer = Lexer(template_source, None)
lexer.tokenize()
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), "../test/integration/django"))
from django.template.base import Lexer, Parser
from django.conf import settings
from django.apps import apps
import time
template_source = u"""
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}" />{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block bodyclass %}{{ block.super }} dashboard{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block content %}
<div id="content-main">
{% if app_list %}
{% for app in app_list %}
<div class="app-{{ app.app_label }} module">
<table>
<caption>
<a href="{{ app.app_url }}" class="section" title="{% blocktrans with name=app.name %}Models in the {{ name }} application{% endblocktrans %}">{{ app.name }}</a>
</caption>
{% for model in app.models %}
<tr class="model-{{ model.object_name|lower }}">
{% if model.admin_url %}
<th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
{% else %}
<th scope="row">{{ model.name }}</th>
{% endif %}
{% if model.add_url %}
<td><a href="{{ model.add_url }}" class="addlink">{% trans 'Add' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
{% if model.admin_url %}
<td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
{% else %}
<td>&nbsp;</td>
{% endif %}
</tr>
{% endfor %}
</table>
</div>
{% endfor %}
{% else %}
<p>{% trans "You don't have permission to edit anything." %}</p>
{% endif %}
</div>
{% endblock %}
{% block sidebar %}
<div id="content-related">
<div class="module" id="recent-actions-module">
<h2>{% trans 'Recent Actions' %}</h2>
<h3>{% trans 'My Actions' %}</h3>
{% load log %}
{% get_admin_log 10 as admin_log for_user user %}
{% if not admin_log %}
<p>{% trans 'None available' %}</p>
{% else %}
<ul class="actionlist">
{% for entry in admin_log %}
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
{% if entry.is_deletion or not entry.get_admin_url %}
{{ entry.object_repr }}
{% else %}
<a href="{{ entry.get_admin_url }}">{{ entry.object_repr }}</a>
{% endif %}
<br/>
{% if entry.content_type %}
<span class="mini quiet">{% filter capfirst %}{% trans entry.content_type.name %}{% endfilter %}</span>
{% else %}
<span class="mini quiet">{% trans 'Unknown content' %}</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
{% endblock %}
"""
settings.configure()
apps.populate((
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
))
elapsed = 0
lexer = Lexer(template_source, None)
tokens = lexer.tokenize()
for i in xrange(500):
parser = Parser(list(tokens))
parser.parse()
......@@ -247,6 +247,7 @@ Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, A
}
ParamReceiveSpec paramspec(0, 0, false, false);
Box** defaults = NULL;
if (call_flags == METH_NOARGS) {
paramspec = ParamReceiveSpec(1, 0, false, false);
} else if (call_flags == METH_VARARGS) {
......@@ -255,6 +256,25 @@ Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, A
paramspec = ParamReceiveSpec(1, 0, true, true);
} else if (call_flags == METH_O) {
paramspec = ParamReceiveSpec(2, 0, false, false);
} else if ((call_flags & ~(METH_O3 | METH_D3)) == 0) {
int num_args = 0;
if (call_flags & METH_O)
num_args++;
if (call_flags & METH_O2)
num_args += 2;
int num_defaults = 0;
if (call_flags & METH_D1)
num_defaults++;
if (call_flags & METH_D2)
num_defaults += 2;
paramspec = ParamReceiveSpec(1 + num_args, num_defaults, false, false);
if (num_defaults) {
static Box* _defaults[] = { NULL, NULL, NULL };
assert(num_defaults <= 3);
defaults = _defaults;
}
} else {
RELEASE_ASSERT(0, "0x%x", call_flags);
}
......@@ -264,9 +284,15 @@ Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, A
Box* oarg3 = NULL;
Box** oargs = NULL;
Box* oargs_array[1];
if (paramspec.totalReceived() >= 3) {
assert((paramspec.totalReceived() - 3) <= sizeof(oargs_array) / sizeof(oargs_array[0]));
oargs = oargs_array;
}
bool rewrite_success = false;
rearrangeArguments(paramspec, NULL, self->method->ml_name, NULL, rewrite_args, rewrite_success, argspec, arg1, arg2,
arg3, args, keyword_names, oarg1, oarg2, oarg3, args);
rearrangeArguments(paramspec, NULL, self->method->ml_name, defaults, rewrite_args, rewrite_success, argspec, arg1,
arg2, arg3, args, keyword_names, oarg1, oarg2, oarg3, oargs);
if (!rewrite_success)
rewrite_args = NULL;
......@@ -321,6 +347,25 @@ Box* BoxedMethodDescriptor::tppCall(Box* _self, CallRewriteArgs* rewrite_args, A
if (rewrite_args)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
rewrite_args->arg2);
} else if ((call_flags & ~(METH_O3 | METH_D3)) == 0) {
{
UNAVOIDABLE_STAT_TIMER(t0, "us_timer_in_builtins");
rtn = ((Box * (*)(Box*, Box*, Box*, Box**))self->method->ml_meth)(oarg1, oarg2, oarg3, oargs);
}
if (rewrite_args) {
if (paramspec.totalReceived() == 2)
rewrite_args->out_rtn = rewrite_args->rewriter->call(true, (void*)self->method->ml_meth,
rewrite_args->arg1, rewrite_args->arg2);
else if (paramspec.totalReceived() == 3)
rewrite_args->out_rtn = rewrite_args->rewriter->call(
true, (void*)self->method->ml_meth, rewrite_args->arg1, rewrite_args->arg2, rewrite_args->arg3);
else if (paramspec.totalReceived() > 3)
rewrite_args->out_rtn
= rewrite_args->rewriter->call(true, (void*)self->method->ml_meth, rewrite_args->arg1,
rewrite_args->arg2, rewrite_args->arg3, rewrite_args->args);
else
abort();
}
} else {
RELEASE_ASSERT(0, "0x%x", call_flags);
}
......
......@@ -2655,7 +2655,7 @@ static PyBufferProcs string_as_buffer = {
};
static PyMethodDef string_methods[] = {
{ "count", (PyCFunction)string_count, METH_VARARGS, NULL },
{ "count", (PyCFunction)string_count, METH_O3 | METH_D2, NULL },
{ "join", (PyCFunction)string_join, METH_O, NULL },
{ "split", (PyCFunction)string_split, METH_VARARGS, NULL },
{ "rsplit", (PyCFunction)string_rsplit, METH_VARARGS, NULL },
......
......@@ -2903,6 +2903,13 @@ extern "C" PyUnicodeObject* _PyUnicode_New(Py_ssize_t length) noexcept {
if (!str)
return (PyUnicodeObject*)PyErr_NoMemory();
#if STAT_ALLOCATIONS
{
size_t size = sizeof(PyUnicodeObject);
ALLOC_STATS(unicode_cls);
}
#endif
// Do a bunch of inlining + constant folding of this line of CPython's:
// unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type);
assert(PyUnicode_Type.tp_basicsize == sizeof(PyUnicodeObject)); // use the compile-time constant
......
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