Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
1c1a34e4
Commit
1c1a34e4
authored
Sep 25, 2014
by
Travis Hance
Committed by
Travis Hance
Oct 29, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added extension module testing capabilities and the rest of the descriptor field types
parent
d8a02b3d
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
807 additions
and
120 deletions
+807
-120
include/Python.h
include/Python.h
+0
-4
include/object.h
include/object.h
+9
-4
src/Makefile
src/Makefile
+13
-7
src/asm_writing/assembler.cpp
src/asm_writing/assembler.cpp
+138
-7
src/asm_writing/assembler.h
src/asm_writing/assembler.h
+29
-1
src/asm_writing/rewriter.cpp
src/asm_writing/rewriter.cpp
+112
-11
src/asm_writing/rewriter.h
src/asm_writing/rewriter.h
+51
-2
src/runtime/capi.cpp
src/runtime/capi.cpp
+6
-4
src/runtime/capi.h
src/runtime/capi.h
+3
-1
src/runtime/complex.cpp
src/runtime/complex.cpp
+2
-2
src/runtime/import.cpp
src/runtime/import.cpp
+5
-2
src/runtime/long.cpp
src/runtime/long.cpp
+12
-0
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+111
-36
src/runtime/types.h
src/runtime/types.h
+14
-0
test/test.cpp
test/test.cpp
+24
-0
test/test_extension/basic_test.c
test/test_extension/basic_test.c
+2
-2
test/test_extension/descr_test.c
test/test_extension/descr_test.c
+217
-0
test/test_extension/setup.py
test/test_extension/setup.py
+5
-4
test/tests/class_noctor.py
test/tests/class_noctor.py
+3
-0
test/tests/extension.expected
test/tests/extension.expected
+0
-4
test/tests/extension.py
test/tests/extension.py
+9
-5
test/tests/member_descriptor_ics.py
test/tests/member_descriptor_ics.py
+36
-23
test/tests/object_new_arguments.py
test/tests/object_new_arguments.py
+3
-0
tools/tester.py
tools/tester.py
+3
-1
No files found.
include/Python.h
View file @
1c1a34e4
...
...
@@ -86,10 +86,6 @@ int PyDict_SetItemString(PyObject* mp, const char* key, PyObject* item);
PyObject
*
PyModule_GetDict
(
PyObject
*
);
PyObject
*
PyDict_New
(
void
);
#define Py_XDECREF(op) (op)
#define Py_INCREF(op) (op)
#define Py_DECREF(op) (op)
#define PyDoc_VAR(name) static char name[]
#define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
#define PyDoc_STR(str) str
...
...
include/object.h
View file @
1c1a34e4
...
...
@@ -824,9 +824,14 @@ PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force);
(*Py_TYPE(op)->tp_dealloc)((PyObject *)(op)))
#endif
/* !Py_TRACE_REFS */
// Pyston change: made Py_INCREF and Py_DECREF into noops
#define Py_INCREF(op) (op)
#define Py_DECREF(op) (op)
// written in a way that won't give "value not used" warnings. Use this empty
// method instead:
static
void
_Py_do_nothing
(
PyObject
*
unused
)
{
}
#define Py_INCREF(op) (_Py_do_nothing((PyObject*)(op)))
#define Py_DECREF(op) (_Py_do_nothing((PyObject*)(op)))
/* Safely decref `op` and set `op` to NULL, especially useful in tp_clear
* and tp_dealloc implementatons.
...
...
@@ -873,8 +878,8 @@ PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force);
/* Macros to use in case the object pointer may be NULL: */
// Pyston change: made these noops as well
#define Py_XINCREF(op) (
op
)
#define Py_XDECREF(op) (
op
)
#define Py_XINCREF(op) (
_Py_do_nothing((PyObject*)(op))
)
#define Py_XDECREF(op) (
_Py_do_nothing((PyObject*)(op))
)
/*
These are provided as conveniences to Python runtime embedders, so that
...
...
src/Makefile
View file @
1c1a34e4
...
...
@@ -360,7 +360,7 @@ cpplint:
check
:
@
# These are ordered roughly in decreasing order of
(
chance will expose issue
)
/
(
time
to run
test
)
$(MAKE)
lint
$(MAKE)
ext pyston_dbg
$(MAKE)
ext
_python ext_pyston
pyston_dbg
$(MAKE)
check_dbg
...
...
@@ -739,12 +739,12 @@ $(patsubst %, $$1: %/$$1 ;,$(EXTRA_SEARCH_DIRS))
)
endef
RUN_DEPS
:=
ext
RUN_DEPS
:=
ext
_pyston
define
make_target
$(eval
\
.PHONY
:
test$1 check$1
check$1 test$1
:
pyston$1 ext
check$1 test$1
:
pyston$1 ext
_pyston
python ../tools/tester.py
-R
pyston
$1
-j
$(TEST_THREADS)
-k
$(TESTS_DIR)
$(ARGS)
python ../tools/tester.py
-R
pyston
$1
-j
$(TEST_THREADS)
-a
-n
-k
$(TESTS_DIR)
$(ARGS)
python ../tools/tester.py
-R
pyston
$1
-j
$(TEST_THREADS)
-a
-O
-k
$(TESTS_DIR)
$(ARGS)
...
...
@@ -899,13 +899,19 @@ test_cpp_ll:
less test.ll
rm
test.ll
.PHONY
:
ext
ext
:
../test/test_extension/test.so
../test/test_extension/test.so
:
../test/test_extension/test.o $(BUILD_SYSTEM_DEPS)
TEST_EXT_MODULE_NAMES
:=
basic_test descr_test
.PHONY
:
ext_pyston
ext_pyston
:
$(TEST_EXT_MODULE_NAMES:%=../test/test_extension/%.pyston.so)
../test/test_extension/%.pyston.so
:
../test/test_extension/%.o $(BUILD_SYSTEM_DEPS)
$(CLANG_EXE)
-shared
$<
-o
$@
-g
../test/test_extension/
test.o
:
../test/test_extension/test
.c $(wildcard ../include/*.h) $(BUILD_SYSTEM_DEPS)
../test/test_extension/
%.o
:
../test/test_extension/%
.c $(wildcard ../include/*.h) $(BUILD_SYSTEM_DEPS)
$(CLANG_EXE)
-O2
-fPIC
-Wimplicit
-I
../include
-c
$<
-o
$@
-g
.PHONY
:
ext_python
ext_python
:
$(TEST_EXT_MODULE_NAMES:%=../test/test_extension/*.c)
cd
../test/test_extension
;
python setup.py build
;
cd
-
$(FROM_CPYTHON_SRCS
:
.c=.o): %.o: %.c $(BUILD_SYSTEM_DEPS)
$(ECHO)
Compiling C file to
$@
$(VERB)
$(CC)
$(EXT_CFLAGS)
-c
$<
-o
$@
-g
-MMD
-MP
-MF
$(
patsubst
%.o,%.d,
$@
)
-O0
...
...
src/asm_writing/assembler.cpp
View file @
1c1a34e4
...
...
@@ -122,9 +122,7 @@ void Assembler::emitInt(int64_t n, int bytes) {
}
void
Assembler
::
emitRex
(
uint8_t
rex
)
{
if
(
rex
!=
0
)
{
emitByte
(
rex
|
0x40
);
}
emitByte
(
rex
|
0x40
);
}
void
Assembler
::
emitModRM
(
uint8_t
mod
,
uint8_t
reg
,
uint8_t
rm
)
{
...
...
@@ -141,8 +139,6 @@ void Assembler::emitSIB(uint8_t scalebits, uint8_t index, uint8_t base) {
emitByte
((
scalebits
<<
6
)
|
(
index
<<
3
)
|
base
);
}
void
Assembler
::
mov
(
Immediate
val
,
Register
dest
)
{
int
rex
=
REX_W
;
...
...
@@ -263,15 +259,63 @@ void Assembler::mov(Register src, Indirect dest) {
}
}
void
Assembler
::
mov
(
Indirect
src
,
Register
dest
,
MovType
type
)
{
void
Assembler
::
mov
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
Q
);
}
void
Assembler
::
movq
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
Q
);
}
void
Assembler
::
movl
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
L
);
}
void
Assembler
::
movb
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
B
);
}
void
Assembler
::
movzbl
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
ZBL
);
}
void
Assembler
::
movsbl
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
SBL
);
}
void
Assembler
::
movzwl
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
ZBL
);
}
void
Assembler
::
movswl
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
SBL
);
}
void
Assembler
::
movzbq
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
ZBQ
);
}
void
Assembler
::
movsbq
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
SBQ
);
}
void
Assembler
::
movzwq
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
ZWQ
);
}
void
Assembler
::
movswq
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
SWQ
);
}
void
Assembler
::
movslq
(
Indirect
src
,
Register
dest
)
{
mov_generic
(
src
,
dest
,
MovType
::
SLQ
);
}
void
Assembler
::
mov_generic
(
Indirect
src
,
Register
dest
,
MovType
type
)
{
int
rex
;
switch
(
type
)
{
case
MovType
:
:
Q
:
case
MovType
:
:
ZBQ
:
case
MovType
:
:
SBQ
:
case
MovType
:
:
ZWQ
:
case
MovType
:
:
SWQ
:
case
MovType
:
:
SLQ
:
rex
=
REX_W
;
break
;
case
MovType
:
:
L
:
case
MovType
:
:
B
:
case
MovType
:
:
ZBL
:
case
MovType
:
:
SBL
:
case
MovType
:
:
ZWL
:
case
MovType
:
:
SWL
:
rex
=
0
;
break
;
default:
...
...
@@ -302,10 +346,29 @@ void Assembler::mov(Indirect src, Register dest, MovType type) {
case
MovType
:
:
B
:
emitByte
(
0x8a
);
break
;
case
MovType
:
:
ZBQ
:
case
MovType
:
:
ZBL
:
emitByte
(
0x0f
);
emitByte
(
0xb6
);
break
;
case
MovType
:
:
SBQ
:
case
MovType
:
:
SBL
:
emitByte
(
0x0f
);
emitByte
(
0xbe
);
break
;
case
MovType
:
:
ZWQ
:
case
MovType
:
:
ZWL
:
emitByte
(
0x0f
);
emitByte
(
0xb7
);
break
;
case
MovType
:
:
SWQ
:
case
MovType
:
:
SWL
:
emitByte
(
0x0f
);
emitByte
(
0xbf
);
break
;
case
MovType
:
:
SLQ
:
emitByte
(
0x63
);
break
;
default:
RELEASE_ASSERT
(
false
,
"unrecognized MovType"
);
}
...
...
@@ -444,6 +507,74 @@ void Assembler::movsd(Indirect src, XMMRegister dest) {
}
}
void
Assembler
::
movss
(
Indirect
src
,
XMMRegister
dest
)
{
int
rex
=
0
;
int
src_idx
=
src
.
base
.
regnum
;
int
dest_idx
=
dest
.
regnum
;
if
(
src_idx
>=
8
)
{
trap
();
rex
|=
REX_R
;
src_idx
-=
8
;
}
if
(
dest_idx
>=
8
)
{
trap
();
rex
|=
REX_B
;
dest_idx
-=
8
;
}
emitByte
(
0xf3
);
if
(
rex
)
emitRex
(
rex
);
emitByte
(
0x0f
);
emitByte
(
0x10
);
bool
needssib
=
(
src_idx
==
0b100
);
int
mode
;
if
(
src
.
offset
==
0
)
mode
=
0b00
;
else
if
(
-
0x80
<=
src
.
offset
&&
src
.
offset
<
0x80
)
mode
=
0b01
;
else
mode
=
0b10
;
emitModRM
(
mode
,
dest_idx
,
src_idx
);
if
(
needssib
)
emitSIB
(
0b00
,
0b100
,
src_idx
);
if
(
mode
==
0b01
)
{
emitByte
(
src
.
offset
);
}
else
if
(
mode
==
0b10
)
{
emitInt
(
src
.
offset
,
4
);
}
}
void
Assembler
::
cvtss2sd
(
XMMRegister
src
,
XMMRegister
dest
)
{
int
rex
=
0
;
int
src_idx
=
src
.
regnum
;
int
dest_idx
=
dest
.
regnum
;
if
(
src_idx
>=
8
)
{
trap
();
rex
|=
REX_R
;
src_idx
-=
8
;
}
if
(
dest_idx
>=
8
)
{
trap
();
rex
|=
REX_B
;
dest_idx
-=
8
;
}
emitByte
(
0xf3
);
if
(
rex
)
emitRex
(
rex
);
emitByte
(
0x0f
);
emitByte
(
0x5a
);
emitModRM
(
0b11
,
src_idx
,
dest_idx
);
}
void
Assembler
::
push
(
Register
reg
)
{
// assert(0 && "This breaks unwinding, please don't use.");
...
...
@@ -744,7 +875,7 @@ void Assembler::emitBatchPop(int scratch_rbp_offset, int scratch_size, const std
if
(
r
.
type
==
GenericRegister
::
GP
)
{
Register
gp
=
r
.
gp
;
assert
(
gp
.
regnum
>=
0
&&
gp
.
regnum
<
16
);
mov
(
next_slot
,
gp
);
mov
q
(
next_slot
,
gp
);
offset
+=
8
;
}
else
if
(
r
.
type
==
GenericRegister
::
XMM
)
{
XMMRegister
reg
=
r
.
xmm
;
...
...
src/asm_writing/assembler.h
View file @
1c1a34e4
...
...
@@ -53,6 +53,16 @@ enum class MovType {
L
,
B
,
ZBL
,
SBL
,
ZWL
,
SWL
,
ZBQ
,
SBQ
,
ZWQ
,
SWQ
,
SLQ
,
ZLQ
=
L
,
};
class
Assembler
{
...
...
@@ -87,11 +97,29 @@ public:
void
movq
(
Immediate
imm
,
Indirect
dest
);
void
mov
(
Register
src
,
Register
dest
);
void
mov
(
Register
src
,
Indirect
dest
);
void
mov
(
Indirect
src
,
Register
dest
,
MovType
type
=
MovType
::
Q
);
void
movsd
(
XMMRegister
src
,
XMMRegister
dest
);
void
movsd
(
XMMRegister
src
,
Indirect
dest
);
void
movsd
(
Indirect
src
,
XMMRegister
dest
);
void
movss
(
Indirect
src
,
XMMRegister
dest
);
void
cvtss2sd
(
XMMRegister
src
,
XMMRegister
dest
);
void
mov
(
Indirect
scr
,
Register
dest
);
void
movq
(
Indirect
scr
,
Register
dest
);
void
movl
(
Indirect
scr
,
Register
dest
);
void
movb
(
Indirect
scr
,
Register
dest
);
void
movzbl
(
Indirect
scr
,
Register
dest
);
void
movsbl
(
Indirect
scr
,
Register
dest
);
void
movzwl
(
Indirect
scr
,
Register
dest
);
void
movswl
(
Indirect
scr
,
Register
dest
);
void
movzbq
(
Indirect
scr
,
Register
dest
);
void
movsbq
(
Indirect
scr
,
Register
dest
);
void
movzwq
(
Indirect
scr
,
Register
dest
);
void
movswq
(
Indirect
scr
,
Register
dest
);
void
movslq
(
Indirect
scr
,
Register
dest
);
void
mov_generic
(
Indirect
src
,
Register
dest
,
MovType
type
);
void
push
(
Register
reg
);
void
pop
(
Register
reg
);
...
...
src/asm_writing/rewriter.cpp
View file @
1c1a34e4
...
...
@@ -127,7 +127,7 @@ void Location::dump() const {
RELEASE_ASSERT
(
0
,
"%d"
,
type
);
}
static
bool
isLargeConstant
(
u
int64_t
val
)
{
static
bool
isLargeConstant
(
int64_t
val
)
{
return
(
val
<
(
-
1L
<<
31
)
||
val
>=
(
1L
<<
31
)
-
1
);
}
...
...
@@ -147,6 +147,8 @@ void Rewriter::_addGuard(RewriterVar* var, uint64_t val) {
assembler
->
jne
(
assembler
::
JumpDestination
::
fromStart
(
rewrite
->
getSlotSize
()));
var
->
bumpUse
();
assertConsistent
();
}
void
RewriterVar
::
addGuardNotEq
(
uint64_t
val
)
{
...
...
@@ -165,6 +167,8 @@ void Rewriter::_addGuardNotEq(RewriterVar* var, uint64_t val) {
assembler
->
je
(
assembler
::
JumpDestination
::
fromStart
(
rewrite
->
getSlotSize
()));
var
->
bumpUse
();
assertConsistent
();
}
void
RewriterVar
::
addAttrGuard
(
int
offset
,
uint64_t
val
,
bool
negate
)
{
...
...
@@ -187,6 +191,8 @@ void Rewriter::_addAttrGuard(RewriterVar* var, int offset, uint64_t val, bool ne
assembler
->
jne
(
assembler
::
JumpDestination
::
fromStart
(
rewrite
->
getSlotSize
()));
var
->
bumpUse
();
assertConsistent
();
}
RewriterVar
*
RewriterVar
::
getAttr
(
int
offset
,
Location
dest
,
assembler
::
MovType
type
)
{
...
...
@@ -202,13 +208,47 @@ void Rewriter::_getAttr(RewriterVar* result, RewriterVar* ptr, int offset, Locat
// in the same register as ptr
ptr
->
bumpUse
();
if
(
dest
.
type
==
Location
::
XMMRegister
)
{
assembler
::
XMMRegister
newvar_reg
=
result
->
initializeInXMMReg
(
dest
);
assembler
->
movsd
(
assembler
::
Indirect
(
ptr_reg
,
offset
),
newvar_reg
);
}
else
{
assembler
::
Register
newvar_reg
=
result
->
initializeInReg
(
dest
);
assembler
->
mov
(
assembler
::
Indirect
(
ptr_reg
,
offset
),
newvar_reg
,
type
);
}
assembler
::
Register
newvar_reg
=
result
->
initializeInReg
(
dest
);
assembler
->
mov_generic
(
assembler
::
Indirect
(
ptr_reg
,
offset
),
newvar_reg
,
type
);
assertConsistent
();
}
RewriterVar
*
RewriterVar
::
getAttrDouble
(
int
offset
,
Location
dest
)
{
RewriterVar
*
result
=
rewriter
->
createNewVar
();
rewriter
->
addAction
([
=
]()
{
rewriter
->
_getAttrDouble
(
result
,
this
,
offset
,
dest
);
},
{
this
},
ActionType
::
NORMAL
);
return
result
;
}
void
Rewriter
::
_getAttrDouble
(
RewriterVar
*
result
,
RewriterVar
*
ptr
,
int
offset
,
Location
dest
)
{
assembler
::
Register
ptr_reg
=
ptr
->
getInReg
();
ptr
->
bumpUse
();
assembler
::
XMMRegister
newvar_reg
=
result
->
initializeInXMMReg
(
dest
);
assembler
->
movsd
(
assembler
::
Indirect
(
ptr_reg
,
offset
),
newvar_reg
);
assertConsistent
();
}
RewriterVar
*
RewriterVar
::
getAttrFloat
(
int
offset
,
Location
dest
)
{
RewriterVar
*
result
=
rewriter
->
createNewVar
();
rewriter
->
addAction
([
=
]()
{
rewriter
->
_getAttrFloat
(
result
,
this
,
offset
,
dest
);
},
{
this
},
ActionType
::
NORMAL
);
return
result
;
}
void
Rewriter
::
_getAttrFloat
(
RewriterVar
*
result
,
RewriterVar
*
ptr
,
int
offset
,
Location
dest
)
{
assembler
::
Register
ptr_reg
=
ptr
->
getInReg
();
ptr
->
bumpUse
();
assembler
::
XMMRegister
newvar_reg
=
result
->
initializeInXMMReg
(
dest
);
assembler
->
movss
(
assembler
::
Indirect
(
ptr_reg
,
offset
),
newvar_reg
);
// cast to double
assembler
->
cvtss2sd
(
newvar_reg
,
newvar_reg
);
assertConsistent
();
}
RewriterVar
*
RewriterVar
::
cmp
(
AST_TYPE
::
AST_TYPE
cmp_type
,
RewriterVar
*
other
,
Location
dest
)
{
...
...
@@ -239,6 +279,8 @@ void Rewriter::_cmp(RewriterVar* result, RewriterVar* v1, AST_TYPE::AST_TYPE cmp
default:
RELEASE_ASSERT
(
0
,
"%d"
,
cmp_type
);
}
assertConsistent
();
}
RewriterVar
*
RewriterVar
::
toBool
(
Location
dest
)
{
...
...
@@ -257,6 +299,8 @@ void Rewriter::_toBool(RewriterVar* result, RewriterVar* var, Location dest) {
assembler
->
test
(
this_reg
,
this_reg
);
assembler
->
setnz
(
result_reg
);
assertConsistent
();
}
void
RewriterVar
::
setAttr
(
int
offset
,
RewriterVar
*
val
)
{
...
...
@@ -267,7 +311,7 @@ void Rewriter::_setAttr(RewriterVar* ptr, int offset, RewriterVar* val) {
assembler
::
Register
ptr_reg
=
ptr
->
getInReg
();
bool
is_immediate
;
assembler
::
Immediate
imm
=
ptr
->
tryGetAsImmediate
(
&
is_immediate
);
assembler
::
Immediate
imm
=
val
->
tryGetAsImmediate
(
&
is_immediate
);
if
(
is_immediate
)
{
assembler
->
movq
(
imm
,
assembler
::
Indirect
(
ptr_reg
,
offset
));
...
...
@@ -280,6 +324,8 @@ void Rewriter::_setAttr(RewriterVar* ptr, int offset, RewriterVar* val) {
ptr
->
bumpUse
();
val
->
bumpUse
();
assertConsistent
();
}
void
RewriterVar
::
dump
()
{
...
...
@@ -450,6 +496,8 @@ void Rewriter::_loadConst(RewriterVar* result, int64_t val, Location dest) {
assembler
::
Register
reg
=
allocReg
(
dest
);
assembler
->
mov
(
assembler
::
Immediate
(
val
),
reg
);
result
->
initializeInReg
(
reg
);
assertConsistent
();
}
RewriterVar
*
Rewriter
::
call
(
bool
can_call_into_python
,
void
*
func_addr
,
RewriterVar
*
arg0
)
{
...
...
@@ -494,6 +542,7 @@ void Rewriter::_call(RewriterVar* result, bool can_call_into_python, void* func_
// TODO figure out why this is here -- what needs to be done differently
// if can_call_into_python is true?
// assert(!can_call_into_python);
assert
(
done_guarding
);
// RewriterVarUsage scratch = createNewVar(Location::any());
assembler
::
Register
r
=
allocReg
(
assembler
::
R11
);
...
...
@@ -530,6 +579,8 @@ void Rewriter::_call(RewriterVar* result, bool can_call_into_python, void* func_
assert
(
var
->
isInLocation
(
Location
::
forArg
(
i
)));
}
assertConsistent
();
for
(
int
i
=
0
;
i
<
args_xmm
.
size
();
i
++
)
{
Location
l
((
assembler
::
XMMRegister
(
i
)));
assert
(
args_xmm
[
i
]
->
isInLocation
(
l
));
...
...
@@ -552,6 +603,8 @@ void Rewriter::_call(RewriterVar* result, bool can_call_into_python, void* func_
arg_xmm
->
bumpUse
();
}
assertConsistent
();
// Spill caller-saved registers:
for
(
auto
check_reg
:
caller_save_registers
)
{
// check_reg.dump();
...
...
@@ -595,6 +648,8 @@ void Rewriter::_call(RewriterVar* result, bool can_call_into_python, void* func_
}
}
assertConsistent
();
#ifndef NDEBUG
for
(
const
auto
&
p
:
vars_by_location
.
getAsMap
())
{
Location
l
=
p
.
first
;
...
...
@@ -611,6 +666,8 @@ void Rewriter::_call(RewriterVar* result, bool can_call_into_python, void* func_
assert
(
vars_by_location
.
count
(
assembler
::
RAX
)
==
0
);
result
->
initializeInReg
(
assembler
::
RAX
);
assertConsistent
();
}
void
Rewriter
::
abort
()
{
...
...
@@ -851,6 +908,33 @@ Location Rewriter::allocScratch() {
RELEASE_ASSERT
(
0
,
"Using all %d bytes of scratch!"
,
scratch_bytes
);
}
RewriterVar
*
Rewriter
::
add
(
RewriterVar
*
a
,
int64_t
b
,
Location
dest
)
{
RewriterVar
*
result
=
createNewVar
();
addAction
([
=
]()
{
this
->
_add
(
result
,
a
,
b
,
dest
);
},
{
a
},
ActionType
::
NORMAL
);
return
result
;
}
void
Rewriter
::
_add
(
RewriterVar
*
result
,
RewriterVar
*
a
,
int64_t
b
,
Location
dest
)
{
// TODO better reg alloc (e.g., mov `a` directly to the dest reg)
assembler
::
Register
newvar_reg
=
allocReg
(
dest
);
assembler
::
Register
a_reg
=
a
->
getInReg
(
Location
::
any
(),
/* allow_constant_in_reg */
true
,
/* otherThan */
newvar_reg
);
assert
(
a_reg
!=
newvar_reg
);
result
->
initializeInReg
(
newvar_reg
);
assembler
->
mov
(
a_reg
,
newvar_reg
);
// TODO we can't rely on this being true, so we need to support the full version
assert
(
!
isLargeConstant
(
b
));
assembler
->
add
(
assembler
::
Immediate
(
b
),
newvar_reg
);
a
->
bumpUse
();
assertConsistent
();
}
RewriterVar
*
Rewriter
::
allocate
(
int
n
)
{
RewriterVar
*
result
=
createNewVar
();
addAction
([
=
]()
{
this
->
_allocate
(
result
,
n
);
},
{},
ActionType
::
NORMAL
);
...
...
@@ -884,6 +968,7 @@ int Rewriter::_allocate(RewriterVar* result, int n) {
vars_by_location
[
m
]
=
LOCATION_PLACEHOLDER
;
}
assertConsistent
();
return
a
;
}
}
else
{
...
...
@@ -914,6 +999,8 @@ void Rewriter::_allocateAndCopy(RewriterVar* result, RewriterVar* array_ptr, int
}
array_ptr
->
bumpUse
();
assertConsistent
();
}
RewriterVar
*
Rewriter
::
allocateAndCopyPlus1
(
RewriterVar
*
first_elem
,
RewriterVar
*
rest_ptr
,
int
n_rest
)
{
...
...
@@ -950,6 +1037,8 @@ void Rewriter::_allocateAndCopyPlus1(RewriterVar* result, RewriterVar* first_ele
}
first_elem
->
bumpUse
();
assertConsistent
();
}
assembler
::
Indirect
Rewriter
::
indirectFor
(
Location
l
)
{
...
...
@@ -962,7 +1051,9 @@ assembler::Indirect Rewriter::indirectFor(Location l) {
return
assembler
::
Indirect
(
assembler
::
RSP
,
l
.
stack_offset
);
}
void
Rewriter
::
spillRegister
(
assembler
::
Register
reg
)
{
void
Rewriter
::
spillRegister
(
assembler
::
Register
reg
,
Location
preserve
)
{
assert
(
preserve
.
type
==
Location
::
Register
||
preserve
.
type
==
Location
::
AnyReg
);
if
(
!
done_guarding
)
{
for
(
int
i
=
0
;
i
<
args
.
size
();
i
++
)
{
assert
(
args
[
i
]
->
arg_loc
!=
Location
(
reg
));
...
...
@@ -984,6 +1075,8 @@ void Rewriter::spillRegister(assembler::Register reg) {
continue
;
if
(
vars_by_location
.
count
(
new_reg
))
continue
;
if
(
Location
(
new_reg
)
==
preserve
)
continue
;
assembler
->
mov
(
reg
,
new_reg
);
addLocationToVar
(
var
,
new_reg
);
...
...
@@ -1041,7 +1134,7 @@ assembler::Register Rewriter::allocReg(Location dest, Location otherThan) {
// Spill the register whose next use is farthest in the future
assert
(
found
);
spillRegister
(
best_reg
);
spillRegister
(
best_reg
,
/* preserve */
otherThan
);
assert
(
vars_by_location
.
count
(
best_reg
)
==
0
);
return
best_reg
;
}
else
if
(
dest
.
type
==
Location
::
Register
)
{
...
...
@@ -1118,6 +1211,14 @@ RewriterVar* Rewriter::createNewVar() {
}
assembler
::
Register
RewriterVar
::
initializeInReg
(
Location
l
)
{
// TODO um should we check this in more places, or what?
// The thing is: if we aren't done guarding, and the register we want to use
// is taken by an arg, we can't spill it, so we shouldn't ask to alloc it.
if
(
l
.
type
==
Location
::
Register
&&
!
rewriter
->
done_guarding
&&
rewriter
->
vars_by_location
[
l
]
!=
NULL
&&
rewriter
->
vars_by_location
[
l
]
->
is_arg
)
{
l
=
Location
::
any
();
}
assembler
::
Register
reg
=
rewriter
->
allocReg
(
l
);
l
=
Location
(
reg
);
...
...
src/asm_writing/rewriter.h
View file @
1c1a34e4
...
...
@@ -193,7 +193,9 @@ public:
}
}
for
(
std
::
pair
<
int32_t
,
RewriterVar
*>
p
:
map_const
)
{
m
.
emplace
(
Location
(
Location
::
Constant
,
p
.
first
),
p
.
second
);
if
(
p
.
second
!=
NULL
)
{
m
.
emplace
(
Location
(
Location
::
Constant
,
p
.
first
),
p
.
second
);
}
}
return
m
;
}
...
...
@@ -212,10 +214,15 @@ public:
void
addGuardNotEq
(
uint64_t
val
);
void
addAttrGuard
(
int
offset
,
uint64_t
val
,
bool
negate
=
false
);
RewriterVar
*
getAttr
(
int
offset
,
Location
loc
=
Location
::
any
(),
assembler
::
MovType
type
=
assembler
::
MovType
::
Q
);
// getAttrFloat casts to double (maybe I should make that separate?)
RewriterVar
*
getAttrFloat
(
int
offset
,
Location
loc
=
Location
::
any
());
RewriterVar
*
getAttrDouble
(
int
offset
,
Location
loc
=
Location
::
any
());
void
setAttr
(
int
offset
,
RewriterVar
*
other
);
RewriterVar
*
cmp
(
AST_TYPE
::
AST_TYPE
cmp_type
,
RewriterVar
*
other
,
Location
loc
=
Location
::
any
());
RewriterVar
*
toBool
(
Location
loc
=
Location
::
any
());
template
<
typename
Src
,
typename
Dst
>
inline
RewriterVar
*
getAttrCast
(
int
offset
,
Location
loc
=
Location
::
any
());
private:
Rewriter
*
rewriter
;
...
...
@@ -331,7 +338,7 @@ private:
assembler
::
Indirect
indirectFor
(
Location
l
);
// Spills a specified register.
// If there are open callee-save registers, takes one of those, otherwise goes on the stack
void
spillRegister
(
assembler
::
Register
reg
);
void
spillRegister
(
assembler
::
Register
reg
,
Location
preserve
=
Location
::
any
()
);
// Similar, but for XMM registers (always go on the stack)
void
spillRegister
(
assembler
::
XMMRegister
reg
);
...
...
@@ -351,6 +358,7 @@ private:
void
_loadConst
(
RewriterVar
*
result
,
int64_t
val
,
Location
loc
);
void
_call
(
RewriterVar
*
result
,
bool
can_call_into_python
,
void
*
func_addr
,
const
std
::
vector
<
RewriterVar
*>&
args
,
const
std
::
vector
<
RewriterVar
*>&
args_xmm
);
void
_add
(
RewriterVar
*
result
,
RewriterVar
*
a
,
int64_t
b
,
Location
dest
);
int
_allocate
(
RewriterVar
*
result
,
int
n
);
void
_allocateAndCopy
(
RewriterVar
*
result
,
RewriterVar
*
array
,
int
n
);
void
_allocateAndCopyPlus1
(
RewriterVar
*
result
,
RewriterVar
*
first_elem
,
RewriterVar
*
rest
,
int
n_rest
);
...
...
@@ -361,6 +369,8 @@ private:
void
_addAttrGuard
(
RewriterVar
*
var
,
int
offset
,
uint64_t
val
,
bool
negate
=
false
);
void
_getAttr
(
RewriterVar
*
result
,
RewriterVar
*
var
,
int
offset
,
Location
loc
=
Location
::
any
(),
assembler
::
MovType
type
=
assembler
::
MovType
::
Q
);
void
_getAttrFloat
(
RewriterVar
*
result
,
RewriterVar
*
var
,
int
offset
,
Location
loc
=
Location
::
any
());
void
_getAttrDouble
(
RewriterVar
*
result
,
RewriterVar
*
var
,
int
offset
,
Location
loc
=
Location
::
any
());
void
_setAttr
(
RewriterVar
*
var
,
int
offset
,
RewriterVar
*
other
);
void
_cmp
(
RewriterVar
*
result
,
RewriterVar
*
var1
,
AST_TYPE
::
AST_TYPE
cmp_type
,
RewriterVar
*
var2
,
Location
loc
=
Location
::
any
());
...
...
@@ -411,6 +421,7 @@ public:
const
std
::
vector
<
RewriterVar
*>&
args_xmm
=
std
::
vector
<
RewriterVar
*>
());
RewriterVar
*
call
(
bool
can_call_into_python
,
void
*
func_addr
,
RewriterVar
*
arg0
);
RewriterVar
*
call
(
bool
can_call_into_python
,
void
*
func_addr
,
RewriterVar
*
arg0
,
RewriterVar
*
arg1
);
RewriterVar
*
add
(
RewriterVar
*
a
,
int64_t
b
,
Location
dest
);
RewriterVar
*
allocate
(
int
n
);
RewriterVar
*
allocateAndCopy
(
RewriterVar
*
array
,
int
n
);
RewriterVar
*
allocateAndCopyPlus1
(
RewriterVar
*
first_elem
,
RewriterVar
*
rest
,
int
n_rest
);
...
...
@@ -452,6 +463,44 @@ bool spillFrameArgumentIfNecessary(StackMap::Record::Location& l, uint8_t*& inst
std
::
pair
<
uint8_t
*
,
uint8_t
*>
initializePatchpoint3
(
void
*
slowpath_func
,
uint8_t
*
start_addr
,
uint8_t
*
end_addr
,
int
scratch_offset
,
int
scratch_size
,
const
std
::
unordered_set
<
int
>&
live_outs
,
SpillMap
&
remapped
);
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
bool
,
bool
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
ZBL
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
char
,
char
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
SBL
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
int8_t
,
int64_t
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
SBQ
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
int16_t
,
int64_t
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
SWQ
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
int32_t
,
int64_t
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
SLQ
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
int64_t
,
int64_t
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
Q
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
uint8_t
,
uint64_t
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
ZBQ
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
uint16_t
,
uint64_t
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
ZWQ
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
uint32_t
,
uint64_t
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
ZLQ
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
uint64_t
,
uint64_t
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
Q
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
long
long
,
long
long
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
Q
);
}
template
<
>
inline
RewriterVar
*
RewriterVar
::
getAttrCast
<
unsigned
long
long
,
unsigned
long
long
>
(
int
offset
,
Location
loc
)
{
return
getAttr
(
offset
,
loc
,
assembler
::
MovType
::
Q
);
}
}
#endif
src/runtime/capi.cpp
View file @
1c1a34e4
...
...
@@ -934,8 +934,9 @@ extern "C" Py_ssize_t PyNumber_AsSsize_t(PyObject* o, PyObject* exc) {
Py_FatalError
(
"unimplemented"
);
}
BoxedModule
*
importTestExtension
()
{
const
char
*
pathname
=
"../test/test_extension/test.so"
;
BoxedModule
*
importTestExtension
(
const
std
::
string
&
name
)
{
std
::
string
pathname_name
=
"../test/test_extension/"
+
name
+
".pyston.so"
;
const
char
*
pathname
=
pathname_name
.
c_str
();
void
*
handle
=
dlopen
(
pathname
,
RTLD_NOW
);
if
(
!
handle
)
{
fprintf
(
stderr
,
"%s
\n
"
,
dlerror
());
...
...
@@ -943,7 +944,8 @@ BoxedModule* importTestExtension() {
}
assert
(
handle
);
void
(
*
init
)()
=
(
void
(
*
)())
dlsym
(
handle
,
"inittest"
);
std
::
string
initname
=
"init"
+
name
;
void
(
*
init
)()
=
(
void
(
*
)())
dlsym
(
handle
,
initname
.
c_str
());
char
*
error
;
if
((
error
=
dlerror
())
!=
NULL
)
{
...
...
@@ -955,7 +957,7 @@ BoxedModule* importTestExtension() {
(
*
init
)();
BoxedDict
*
sys_modules
=
getSysModulesDict
();
Box
*
s
=
boxStrConstant
(
"test"
);
Box
*
s
=
boxStrConstant
(
name
.
c_str
()
);
Box
*
_m
=
sys_modules
->
d
[
s
];
RELEASE_ASSERT
(
_m
,
"module failed to initialize properly?"
);
assert
(
_m
->
cls
==
module_cls
);
...
...
src/runtime/capi.h
View file @
1c1a34e4
...
...
@@ -15,10 +15,12 @@
#ifndef PYSTON_RUNTIME_CAPI_H
#define PYSTON_RUNTIME_CAPI_H
#include <cstring>
namespace
pyston
{
class
BoxedModule
;
BoxedModule
*
importTestExtension
();
BoxedModule
*
importTestExtension
(
const
std
::
string
&
);
}
#endif
src/runtime/complex.cpp
View file @
1c1a34e4
...
...
@@ -252,9 +252,9 @@ void setupComplex() {
complex_cls
->
giveAttr
(
"__str__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
complexStr
,
STR
,
1
)));
complex_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
complexRepr
,
STR
,
1
)));
complex_cls
->
giveAttr
(
"real"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
FLOAT
,
offsetof
(
BoxedComplex
,
real
)));
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
DOUBLE
,
offsetof
(
BoxedComplex
,
real
)));
complex_cls
->
giveAttr
(
"imag"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
FLOAT
,
offsetof
(
BoxedComplex
,
imag
)));
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
DOUBLE
,
offsetof
(
BoxedComplex
,
imag
)));
complex_cls
->
freeze
();
}
...
...
src/runtime/import.cpp
View file @
1c1a34e4
...
...
@@ -84,8 +84,11 @@ static Box* importSub(const std::string* name, Box* parent_module) {
return
module
;
}
if
(
*
name
==
"test"
)
{
return
importTestExtension
();
if
(
*
name
==
"basic_test"
)
{
return
importTestExtension
(
"basic_test"
);
}
if
(
*
name
==
"descr_test"
)
{
return
importTestExtension
(
"descr_test"
);
}
raiseExcHelper
(
ImportError
,
"No module named %s"
,
name
->
c_str
());
...
...
src/runtime/long.cpp
View file @
1c1a34e4
...
...
@@ -132,6 +132,18 @@ extern "C" BoxedLong* boxLong(int64_t n) {
return
rtn
;
}
extern
"C"
PyObject
*
PyLong_FromLongLong
(
long
long
ival
)
{
BoxedLong
*
rtn
=
new
BoxedLong
(
long_cls
);
mpz_init_set_si
(
rtn
->
n
,
ival
);
return
rtn
;
}
extern
"C"
PyObject
*
PyLong_FromUnsignedLongLong
(
unsigned
long
long
ival
)
{
BoxedLong
*
rtn
=
new
BoxedLong
(
long_cls
);
mpz_init_set_ui
(
rtn
->
n
,
ival
);
return
rtn
;
}
extern
"C"
Box
*
longNew
(
Box
*
_cls
,
Box
*
val
,
Box
*
_base
)
{
if
(
!
isSubclass
(
_cls
->
cls
,
type_cls
))
raiseExcHelper
(
TypeError
,
"long.__new__(X): X is not a type object (%s)"
,
getTypeName
(
_cls
)
->
c_str
());
...
...
src/runtime/objmodel.cpp
View file @
1c1a34e4
This diff is collapsed.
Click to expand it.
src/runtime/types.h
View file @
1c1a34e4
...
...
@@ -364,7 +364,21 @@ public:
BYTE
=
T_BYTE
,
INT
=
T_INT
,
OBJECT
=
T_OBJECT
,
OBJECT_EX
=
T_OBJECT_EX
,
FLOAT
=
T_FLOAT
,
SHORT
=
T_SHORT
,
LONG
=
T_LONG
,
DOUBLE
=
T_DOUBLE
,
STRING
=
T_STRING
,
STRING_INPLACE
=
T_STRING_INPLACE
,
CHAR
=
T_CHAR
,
UBYTE
=
T_UBYTE
,
USHORT
=
T_USHORT
,
UINT
=
T_UINT
,
ULONG
=
T_ULONG
,
LONGLONG
=
T_LONGLONG
,
ULONGLONG
=
T_ULONGLONG
,
PYSSIZET
=
T_PYSSIZET
}
type
;
int
offset
;
...
...
test/test.cpp
View file @
1c1a34e4
...
...
@@ -21,3 +21,27 @@ int f() {
extern
"C"
C
*
c
()
{
return
new
C
(
f
());
}
void
moo
(
double
);
float
chrs
[
10
];
void
foo
(
int
i
)
{
moo
(
chrs
[
i
]);
}
void
moo2
(
long
long
);
int
chrs2
[
10
];
void
foo2
(
int
i
)
{
moo2
(
chrs2
[
i
]);
}
void
moo3
(
long
long
);
short
chrs3
[
10
];
void
foo3
(
int
i
)
{
moo3
(
chrs3
[
i
]);
}
void
moo4
(
bool
);
bool
chrs4
[
10
];
void
foo4
(
int
i
)
{
moo4
(
chrs4
[
i
]);
}
test/test_extension/test.c
→
test/test_extension/
basic_
test.c
View file @
1c1a34e4
...
...
@@ -39,11 +39,11 @@ static PyMethodDef TestMethods[] = {
};
PyMODINIT_FUNC
inittest
(
void
)
init
basic_
test
(
void
)
{
PyObject
*
m
;
m
=
Py_InitModule
(
"test"
,
TestMethods
);
m
=
Py_InitModule
(
"
basic_
test"
,
TestMethods
);
if
(
m
==
NULL
)
return
;
}
test/test_extension/descr_test.c
0 → 100644
View file @
1c1a34e4
#include <string.h>
#include <Python.h>
#include <structmember.h>
typedef
struct
{
PyObject_HEAD
short
member_short
;
int
member_int
;
long
member_long
;
float
member_float
;
double
member_double
;
char
*
member_string
;
char
member_string_inplace
[
80
];
char
member_char
;
int8_t
member_byte
;
uint8_t
member_ubyte
;
unsigned
short
member_ushort
;
unsigned
int
member_uint
;
unsigned
long
member_ulong
;
char
member_bool
;
PyObject
*
member_object
;
PyObject
*
member_object_ex
;
long
long
member_long_long
;
unsigned
long
long
member_ulong_long
;
Py_ssize_t
member_pyssizet
;
}
descr_tester_object
;
char
*
string1
=
"string1"
;
char
*
string2
=
"string2"
;
char
*
string_empty
=
""
;
static
struct
PyMemberDef
descr_memberlist
[]
=
{
{
"member_short"
,
T_SHORT
,
offsetof
(
descr_tester_object
,
member_short
),
READONLY
},
{
"member_int"
,
T_INT
,
offsetof
(
descr_tester_object
,
member_int
),
READONLY
},
{
"member_long"
,
T_LONG
,
offsetof
(
descr_tester_object
,
member_long
),
READONLY
},
{
"member_float"
,
T_FLOAT
,
offsetof
(
descr_tester_object
,
member_float
),
READONLY
},
{
"member_double"
,
T_DOUBLE
,
offsetof
(
descr_tester_object
,
member_double
),
READONLY
},
{
"member_string"
,
T_STRING
,
offsetof
(
descr_tester_object
,
member_string
),
READONLY
},
{
"member_string_inplace"
,
T_STRING_INPLACE
,
offsetof
(
descr_tester_object
,
member_string_inplace
),
READONLY
},
{
"member_char"
,
T_CHAR
,
offsetof
(
descr_tester_object
,
member_char
),
READONLY
},
{
"member_byte"
,
T_BYTE
,
offsetof
(
descr_tester_object
,
member_byte
),
READONLY
},
{
"member_ubyte"
,
T_UBYTE
,
offsetof
(
descr_tester_object
,
member_ubyte
),
READONLY
},
{
"member_ushort"
,
T_USHORT
,
offsetof
(
descr_tester_object
,
member_ushort
),
READONLY
},
{
"member_uint"
,
T_UINT
,
offsetof
(
descr_tester_object
,
member_uint
),
READONLY
},
{
"member_ulong"
,
T_ULONG
,
offsetof
(
descr_tester_object
,
member_ulong
),
READONLY
},
{
"member_bool"
,
T_BOOL
,
offsetof
(
descr_tester_object
,
member_bool
),
READONLY
},
{
"member_object"
,
T_OBJECT
,
offsetof
(
descr_tester_object
,
member_object
),
READONLY
},
{
"member_object_ex"
,
T_OBJECT_EX
,
offsetof
(
descr_tester_object
,
member_object_ex
),
READONLY
},
{
"member_long_long"
,
T_LONGLONG
,
offsetof
(
descr_tester_object
,
member_long_long
),
READONLY
},
{
"member_ulong_long"
,
T_ULONGLONG
,
offsetof
(
descr_tester_object
,
member_ulong_long
),
READONLY
},
{
"member_pyssizet"
,
T_PYSSIZET
,
offsetof
(
descr_tester_object
,
member_pyssizet
),
READONLY
},
{
NULL
}
};
static
void
descr_tester_dealloc
(
descr_tester_object
*
mc
)
{
printf
(
"dealloc"
);
if
(
mc
->
member_object
)
Py_DECREF
(
mc
->
member_object
);
if
(
mc
->
member_object_ex
)
Py_DECREF
(
mc
->
member_object_ex
);
PyObject_GC_UnTrack
(
mc
);
PyObject_GC_Del
(
mc
);
printf
(
"done dealloc"
);
}
PyDoc_STRVAR
(
descr_tester_doc
,
"descr_tester doc"
);
static
int
descr_tester_traverse
(
descr_tester_object
*
mc
,
visitproc
visit
,
void
*
arg
)
{
printf
(
"traverse"
);
if
(
mc
->
member_object
!=
NULL
)
Py_VISIT
(
mc
->
member_object
);
if
(
mc
->
member_object_ex
!=
NULL
)
Py_VISIT
(
mc
->
member_object_ex
);
printf
(
"done traverse"
);
return
0
;
}
static
PyTypeObject
descr_tester
;
static
PyObject
*
descr_tester_new
(
PyTypeObject
*
type
,
PyObject
*
args
,
PyObject
*
kwds
)
{
printf
(
"shouldn't get here? (new)"
);
return
NULL
;
}
static
PyObject
*
descr_tester_call
(
descr_tester_object
*
mc
,
PyObject
*
args
,
PyObject
*
kw
)
{
printf
(
"shouldn't get here? (call)"
);
return
NULL
;
}
static
PyTypeObject
descr_tester
=
{
PyVarObject_HEAD_INIT
(
NULL
,
0
)
"descr_test.descr_tester"
,
/* tp_name */
sizeof
(
descr_tester_object
),
/* tp_basicsize */
0
,
/* tp_itemsize */
/* methods */
(
destructor
)
descr_tester_dealloc
,
/* tp_dealloc */
0
,
/* tp_print */
0
,
/* tp_getattr */
0
,
/* tp_setattr */
0
,
/* tp_compare */
0
,
/* tp_repr */
0
,
/* tp_as_number */
0
,
/* tp_as_sequence */
0
,
/* tp_as_mapping */
0
,
/* tp_hash */
(
ternaryfunc
)
descr_tester_call
,
/* tp_call */
0
,
/* tp_str */
PyObject_GenericGetAttr
,
/* tp_getattro */
0
,
/* tp_setattro */
0
,
/* tp_as_buffer */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_HAVE_GC
,
/* tp_flags */
descr_tester_doc
,
/* tp_doc */
(
traverseproc
)
descr_tester_traverse
,
/* tp_traverse */
0
,
/* tp_clear */
0
,
/* tp_richcompare */
0
,
/* tp_weaklistoffset */
0
,
/* tp_iter */
0
,
/* tp_iternext */
0
,
/* tp_methods */
descr_memberlist
,
/* tp_members */
0
,
/* tp_getset */
0
,
/* tp_base */
0
,
/* tp_dict */
0
,
/* tp_descr_get */
0
,
/* tp_descr_set */
0
,
/* tp_dictoffset */
0
,
/* tp_init */
0
,
/* tp_alloc */
descr_tester_new
,
/* tp_new */
0
,
/* tp_free */
};
static
PyMethodDef
DescrTestMethods
[]
=
{
{
NULL
,
NULL
,
0
,
NULL
}
/* Sentinel */
};
PyMODINIT_FUNC
initdescr_test
(
void
)
{
int
res
=
PyType_Ready
(
&
descr_tester
);
if
(
res
<
0
)
return
;
Py_INCREF
(
&
descr_tester
);
descr_tester_object
*
o1
=
PyObject_New
(
descr_tester_object
,
&
descr_tester
);
if
(
o1
==
NULL
)
return
;
o1
->
member_short
=
SHRT_MAX
;
o1
->
member_int
=
INT_MAX
;
o1
->
member_long
=
LONG_MAX
;
o1
->
member_float
=
1
.
0
f
;
o1
->
member_double
=
2
.
0
;
o1
->
member_string
=
string1
;
strcpy
(
o1
->
member_string_inplace
,
string2
);
o1
->
member_char
=
'A'
;
o1
->
member_byte
=
CHAR_MAX
;
o1
->
member_ubyte
=
UCHAR_MAX
;
o1
->
member_ushort
=
USHRT_MAX
;
o1
->
member_uint
=
UINT_MAX
;
o1
->
member_ulong
=
ULONG_MAX
;
o1
->
member_bool
=
1
;
o1
->
member_object
=
PyInt_FromLong
(
15
);
o1
->
member_object_ex
=
PyInt_FromLong
(
16
);
o1
->
member_long_long
=
LLONG_MAX
;
o1
->
member_ulong_long
=
ULLONG_MAX
;
o1
->
member_pyssizet
=
(
Py_ssize_t
)((
1ULL
<<
(
8
*
sizeof
(
Py_ssize_t
)
-
1
))
-
1
);
// max Py_ssize_t
Py_INCREF
(
o1
);
Py_INCREF
(
o1
->
member_object
);
Py_INCREF
(
o1
->
member_object_ex
);
descr_tester_object
*
o2
=
PyObject_GC_New
(
descr_tester_object
,
&
descr_tester
);
if
(
o2
==
NULL
)
return
;
o2
->
member_short
=
SHRT_MIN
;
o2
->
member_int
=
INT_MIN
;
o2
->
member_long
=
LONG_MIN
;
o2
->
member_float
=
3
.
0
f
;
o2
->
member_double
=
4
.
0
;
o2
->
member_string
=
NULL
;
// let's see what happens!
strcpy
(
o2
->
member_string_inplace
,
string_empty
);
o2
->
member_char
=
'a'
;
o2
->
member_byte
=
CHAR_MIN
;
o2
->
member_ubyte
=
0
;
o2
->
member_ushort
=
0
;
o2
->
member_uint
=
0
;
o2
->
member_ulong
=
0
;
o2
->
member_bool
=
0
;
o2
->
member_object
=
NULL
;
// None
o2
->
member_object_ex
=
NULL
;
// Exception
o2
->
member_long_long
=
LLONG_MIN
;
o2
->
member_ulong_long
=
0
;
o2
->
member_pyssizet
=
o1
->
member_pyssizet
+
1
;
// min Py_ssize_t
Py_INCREF
(
o2
);
PyObject
*
m
;
m
=
Py_InitModule
(
"descr_test"
,
DescrTestMethods
);
if
(
m
==
NULL
)
return
;
PyModule_AddObject
(
m
,
"descr_tester"
,
(
PyObject
*
)
&
descr_tester
);
PyModule_AddObject
(
m
,
"member_descr_object1"
,
(
PyObject
*
)
o1
);
PyModule_AddObject
(
m
,
"member_descr_object2"
,
(
PyObject
*
)
o2
);
}
test/test_extension/setup.py
View file @
1c1a34e4
from
distutils.core
import
setup
,
Extension
test_module
=
Extension
(
"test"
,
sources
=
[
"test.c"
])
setup
(
name
=
"test"
,
version
=
"1.0"
,
description
=
"test"
,
ext_modules
=
[
test_module
],
)
ext_modules
=
[
Extension
(
"basic_test"
,
sources
=
[
"basic_test.c"
]),
Extension
(
"descr_test"
,
sources
=
[
"descr_test.c"
]),
],
)
test/tests/class_noctor.py
View file @
1c1a34e4
# skip-if: sys.version_info.micro >= 4
# - Error message changed in 2.7.4
# Regression test:
# If the init function doesn't exist, shouldn't just silently ignore any args
# that got passed
...
...
test/tests/extension.expected
deleted
100644 → 0
View file @
d8a02b3d
<module 'test' from '../test/test_extension/test.so'>
[]
This will break
[]
test/tests/extension.py
View file @
1c1a34e4
import
test
# expected: fail
# This test case currently fails because it prints the relative path to the .so
# module rather than the absolute path.
print
test
import
basic_test
print
basic_test
# TODO this should work even if we don't keep a reference to l;
# it doesn't currently always work, but it sometimes works, so it's hard
...
...
@@ -8,8 +12,8 @@ print test
# Instead just weaken the test, and add this TODO to add the harder test back
# later.
l
=
[]
test
.
store
(
l
)
print
test
.
load
()
basic_
test
.
store
(
l
)
print
basic_
test
.
load
()
class
C
(
object
):
def
__init__
(
self
):
...
...
@@ -19,4 +23,4 @@ for i in xrange(100000):
C
()
print
"This will break"
print
test
.
load
()
print
basic_
test
.
load
()
test/tests/member_descriptor_ics.py
View file @
1c1a34e4
# run_args: -n
# statcheck: noninit_count('slowpath_member_descriptor_get') <=
5
0
# statcheck: noninit_count('slowpath_member_descriptor_get') <=
150
0
f
=
open
(
"/dev/null"
)
# Right now this will fail for the access with the try-block.
# All other accesses should be re-written.
def
go
():
# object
s
=
slice
(
i
,
1.0
,
"abc"
)
print
s
.
start
print
s
.
stop
print
s
.
step
import
descr_test
# byte
# TODO
# using softspace works for this test as long as we implement softspace as
# a member descriptor but it should actually a getset_descriptor
# in addition to fixing that, we should replace it in this test with a legit
# member descriptor
print
f
.
softspace
def
f
(
o
,
expect_exc
):
# print the repr so we make sure we get the types right (int or long)
# TODO figure out what uses BOOL and test that
# TODO figure out what uses INT and test that
# float
c
=
1j
+
i
print
c
.
real
print
c
.
imag
print
'short'
,
repr
(
o
.
member_short
)
print
'int'
,
repr
(
o
.
member_int
)
print
'long'
,
repr
(
o
.
member_long
)
print
'float'
,
repr
(
o
.
member_float
)
print
'double'
,
repr
(
o
.
member_double
)
print
'string'
,
repr
(
o
.
member_string
)
print
'string_inplace'
,
repr
(
o
.
member_string_inplace
)
print
'char'
,
repr
(
o
.
member_char
)
print
'byte'
,
repr
(
o
.
member_byte
)
print
'ubyte'
,
repr
(
o
.
member_ubyte
)
print
'ushort'
,
repr
(
o
.
member_ushort
)
print
'uint'
,
repr
(
o
.
member_uint
)
print
'ulong'
,
repr
(
o
.
member_ulong
)
print
'bool'
,
repr
(
o
.
member_bool
)
print
'object'
,
repr
(
o
.
member_object
)
if
expect_exc
:
try
:
o
.
member_object_ex
except
AttributeError
as
e
:
print
'object_ex got AttributeError'
,
e
.
message
else
:
print
'object_ex'
,
repr
(
o
.
member_object_ex
)
print
'long_long'
,
repr
(
o
.
member_long_long
)
print
'ulong_long'
,
repr
(
o
.
member_ulong_long
)
print
'pyssizet'
,
repr
(
o
.
member_pyssizet
)
for
i
in
xrange
(
1000
):
go
();
print
"1:"
f
(
descr_test
.
member_descr_object1
,
False
)
print
"2:"
f
(
descr_test
.
member_descr_object2
,
True
)
test/tests/object_new_arguments.py
View file @
1c1a34e4
# skip-if: sys.version_info.micro >= 4
# - Error message changed in 2.7.4
# object.__new__ doesn't complain if __init__ is overridden:
class
C1
(
object
):
...
...
tools/tester.py
View file @
1c1a34e4
...
...
@@ -68,7 +68,9 @@ def get_expected_output(fn):
pass
# TODO don't suppress warnings globally:
p
=
subprocess
.
Popen
([
"python"
,
"-Wignore"
,
fn
],
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
stdin
=
open
(
"/dev/null"
),
preexec_fn
=
set_ulimits
)
env
=
dict
(
os
.
environ
)
env
[
"PYTHONPATH"
]
=
"../test/test_extension/build/lib.linux-x86_64-2.7/"
p
=
subprocess
.
Popen
([
"python"
,
"-Wignore"
,
fn
],
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
,
stdin
=
open
(
"/dev/null"
),
preexec_fn
=
set_ulimits
,
env
=
env
)
out
,
err
=
p
.
communicate
()
code
=
p
.
wait
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment