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
bfbcc4b9
Commit
bfbcc4b9
authored
Sep 23, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #919 from kmod/sqlalchemy_merge
Misc fixes for sqlalchemy
parents
6fd55fdd
b5edf37f
Changes
24
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
258 additions
and
119 deletions
+258
-119
src/analysis/type_analysis.cpp
src/analysis/type_analysis.cpp
+7
-8
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+21
-0
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+25
-56
src/codegen/irgen/util.cpp
src/codegen/irgen/util.cpp
+1
-1
src/codegen/runtime_hooks.cpp
src/codegen/runtime_hooks.cpp
+1
-0
src/codegen/runtime_hooks.h
src/codegen/runtime_hooks.h
+1
-1
src/core/ast.cpp
src/core/ast.cpp
+1
-0
src/core/ast.h
src/core/ast.h
+3
-0
src/core/types.h
src/core/types.h
+4
-1
src/gc/collector.cpp
src/gc/collector.cpp
+25
-11
src/gc/gc.h
src/gc/gc.h
+8
-8
src/gc/gc_alloc.h
src/gc/gc_alloc.h
+0
-2
src/gc/heap.cpp
src/gc/heap.cpp
+6
-3
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+1
-1
src/runtime/inline/link_forcer.cpp
src/runtime/inline/link_forcer.cpp
+1
-0
src/runtime/list.cpp
src/runtime/list.cpp
+1
-0
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+18
-10
src/runtime/types.cpp
src/runtime/types.cpp
+64
-16
src/runtime/types.h
src/runtime/types.h
+6
-0
test/integration/sqlalchemy_smalltest.py
test/integration/sqlalchemy_smalltest.py
+2
-1
test/tests/closure_test.py
test/tests/closure_test.py
+12
-0
test/tests/dir.py
test/tests/dir.py
+21
-0
test/tests/hasattr_guarding.py
test/tests/hasattr_guarding.py
+23
-0
test/tests/print.py
test/tests/print.py
+6
-0
No files found.
src/analysis/type_analysis.cpp
View file @
bfbcc4b9
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
#include "runtime/types.h"
#include "runtime/types.h"
//#undef VERBOSITY
//#undef VERBOSITY
//#define VERBOSITY(x)
2
//#define VERBOSITY(x)
4
namespace
pyston
{
namespace
pyston
{
...
@@ -116,9 +116,11 @@ private:
...
@@ -116,9 +116,11 @@ private:
if
(
speculated_cls
!=
NULL
&&
speculated_cls
->
is_constant
)
{
if
(
speculated_cls
!=
NULL
&&
speculated_cls
->
is_constant
)
{
ConcreteCompilerType
*
speculated_type
=
unboxedType
(
typeFromClass
(
speculated_cls
));
ConcreteCompilerType
*
speculated_type
=
unboxedType
(
typeFromClass
(
speculated_cls
));
if
(
VERBOSITY
()
>=
2
)
{
if
(
VERBOSITY
()
>=
2
)
{
printf
(
"in propagator, speculating that %s would actually be %s, at
:
\n
"
,
old_type
->
debugName
().
c_str
(),
printf
(
"in propagator, speculating that %s would actually be %s, at
"
,
old_type
->
debugName
().
c_str
(),
speculated_type
->
debugName
().
c_str
());
speculated_type
->
debugName
().
c_str
());
fflush
(
stdout
);
print_ast
(
node
);
print_ast
(
node
);
llvm
::
outs
().
flush
();
printf
(
"
\n
"
);
printf
(
"
\n
"
);
}
}
...
@@ -152,8 +154,9 @@ private:
...
@@ -152,8 +154,9 @@ private:
CompilerType
*
rtn
=
static_cast
<
CompilerType
*>
(
raw_rtn
);
CompilerType
*
rtn
=
static_cast
<
CompilerType
*>
(
raw_rtn
);
if
(
VERBOSITY
()
>=
3
)
{
if
(
VERBOSITY
()
>=
3
)
{
printf
(
"Type of "
);
print_ast
(
node
);
print_ast
(
node
);
printf
(
" %s
\n
"
,
rtn
->
debugName
().
c_str
());
printf
(
"
is
%s
\n
"
,
rtn
->
debugName
().
c_str
());
}
}
expr_types
[
node
]
=
rtn
;
expr_types
[
node
]
=
rtn
;
...
@@ -428,10 +431,6 @@ private:
...
@@ -428,10 +431,6 @@ private:
return
UNKNOWN
;
return
UNKNOWN
;
}
}
if
(
name_scope
==
ScopeInfo
::
VarScopeType
::
CLOSURE
)
{
return
UNKNOWN
;
}
if
(
name_scope
==
ScopeInfo
::
VarScopeType
::
NAME
)
{
if
(
name_scope
==
ScopeInfo
::
VarScopeType
::
NAME
)
{
return
UNKNOWN
;
return
UNKNOWN
;
}
}
...
@@ -440,7 +439,7 @@ private:
...
@@ -440,7 +439,7 @@ private:
return
UNKNOWN
;
return
UNKNOWN
;
}
}
if
(
name_scope
==
ScopeInfo
::
VarScopeType
::
FAST
)
{
if
(
name_scope
==
ScopeInfo
::
VarScopeType
::
FAST
||
name_scope
==
ScopeInfo
::
VarScopeType
::
CLOSURE
)
{
CompilerType
*&
t
=
sym_table
[
node
->
id
];
CompilerType
*&
t
=
sym_table
[
node
->
id
];
if
(
t
==
NULL
)
{
if
(
t
==
NULL
)
{
// if (VERBOSITY() >= 2) {
// if (VERBOSITY() >= 2) {
...
...
src/capi/typeobject.cpp
View file @
bfbcc4b9
...
@@ -977,6 +977,27 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
...
@@ -977,6 +977,27 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
rewrite_args
->
out_rtn
=
grewrite_args
.
out_rtn
;
rewrite_args
->
out_rtn
=
grewrite_args
.
out_rtn
;
rewrite_args
->
out_return_convention
=
grewrite_args
.
out_return_convention
;
rewrite_args
->
out_return_convention
=
grewrite_args
.
out_return_convention
;
}
}
// Guarding here is a bit tricky, since we need to make sure that we call getattr
// (or not) at the right times.
// Right now this section is a bit conservative.
if
(
rewrite_args
)
{
if
(
grewrite_args
.
out_return_convention
==
GetattrRewriteArgs
::
NO_RETURN
)
{
// Do nothing
}
else
if
(
grewrite_args
.
out_return_convention
==
GetattrRewriteArgs
::
VALID_RETURN
)
{
// TODO we should have a HAS_RETURN that takes out the NULL case
assert
(
res
);
if
(
res
)
grewrite_args
.
out_rtn
->
addGuardNotEq
(
0
);
else
grewrite_args
.
out_rtn
->
addGuard
(
0
);
}
else
if
(
grewrite_args
.
out_return_convention
==
GetattrRewriteArgs
::
NOEXC_POSSIBLE
)
{
// TODO maybe we could handle this
rewrite_args
=
NULL
;
}
else
{
RELEASE_ASSERT
(
0
,
"%d"
,
grewrite_args
.
out_return_convention
);
}
}
}
else
{
}
else
{
try
{
try
{
res
=
getattrInternalGeneric
(
self
,
name
,
NULL
,
false
,
false
,
NULL
,
NULL
);
res
=
getattrInternalGeneric
(
self
,
name
,
NULL
,
false
,
false
,
NULL
,
NULL
);
...
...
src/codegen/irgen/irgenerator.cpp
View file @
bfbcc4b9
...
@@ -1170,7 +1170,7 @@ private:
...
@@ -1170,7 +1170,7 @@ private:
llvm
::
Value
*
r
=
emitter
.
createCall3
(
unw_info
,
g
.
funcs
.
boxedLocalsGet
,
boxedLocals
,
attr
,
module
);
llvm
::
Value
*
r
=
emitter
.
createCall3
(
unw_info
,
g
.
funcs
.
boxedLocalsGet
,
boxedLocals
,
attr
,
module
);
return
new
ConcreteCompilerVariable
(
UNKNOWN
,
r
,
true
);
return
new
ConcreteCompilerVariable
(
UNKNOWN
,
r
,
true
);
}
else
{
}
else
{
// vst is one of {FAST, CLOSURE
, NAME
}
// vst is one of {FAST, CLOSURE}
if
(
symbol_table
.
find
(
node
->
id
)
==
symbol_table
.
end
())
{
if
(
symbol_table
.
find
(
node
->
id
)
==
symbol_table
.
end
())
{
// TODO should mark as DEAD here, though we won't end up setting all the names appropriately
// TODO should mark as DEAD here, though we won't end up setting all the names appropriately
// state = DEAD;
// state = DEAD;
...
@@ -1541,14 +1541,24 @@ private:
...
@@ -1541,14 +1541,24 @@ private:
if
(
VERBOSITY
(
"irgen"
)
>=
2
)
{
if
(
VERBOSITY
(
"irgen"
)
>=
2
)
{
printf
(
"Speculating that %s is actually %s, at "
,
rtn
->
getConcreteType
()
->
debugName
().
c_str
(),
printf
(
"Speculating that %s is actually %s, at "
,
rtn
->
getConcreteType
()
->
debugName
().
c_str
(),
speculated_type
->
debugName
().
c_str
());
speculated_type
->
debugName
().
c_str
());
PrintVisitor
printer
;
fflush
(
stdout
);
node
->
accept
(
&
printer
);
print_ast
(
node
);
llvm
::
outs
().
flush
();
printf
(
"
\n
"
);
printf
(
"
\n
"
);
}
}
#ifndef NDEBUG
// That's not really a speculation.... could potentially handle this here, but
// That's not really a speculation.... could potentially handle this here, but
// I think it's better to just not generate bad speculations:
// I think it's better to just not generate bad speculations:
assert
(
!
rtn
->
canConvertTo
(
speculated_type
));
if
(
rtn
->
canConvertTo
(
speculated_type
))
{
auto
source
=
irstate
->
getSourceInfo
();
printf
(
"On %s:%d, function %s:
\n
"
,
source
->
getFn
()
->
c_str
(),
source
->
body
[
0
]
->
lineno
,
source
->
getName
()
->
c_str
());
irstate
->
getSourceInfo
()
->
cfg
->
print
();
}
RELEASE_ASSERT
(
!
rtn
->
canConvertTo
(
speculated_type
),
"%s %s"
,
rtn
->
getType
()
->
debugName
().
c_str
(),
speculated_type
->
debugName
().
c_str
());
#endif
ConcreteCompilerVariable
*
old_rtn
=
rtn
->
makeConverted
(
emitter
,
UNKNOWN
);
ConcreteCompilerVariable
*
old_rtn
=
rtn
->
makeConverted
(
emitter
,
UNKNOWN
);
rtn
->
decvref
(
emitter
);
rtn
->
decvref
(
emitter
);
...
@@ -2003,7 +2013,7 @@ private:
...
@@ -2003,7 +2013,7 @@ private:
ConcreteCompilerVariable
*
dest
=
NULL
;
ConcreteCompilerVariable
*
dest
=
NULL
;
if
(
node
->
dest
)
{
if
(
node
->
dest
)
{
auto
d
=
evalExpr
(
node
->
dest
,
unw_info
);
auto
d
=
evalExpr
(
node
->
dest
,
unw_info
);
dest
=
d
->
makeConverted
(
emitter
,
d
->
get
Concrete
Type
());
dest
=
d
->
makeConverted
(
emitter
,
d
->
get
Box
Type
());
d
->
decvref
(
emitter
);
d
->
decvref
(
emitter
);
}
else
{
}
else
{
llvm
::
Value
*
sys_stdout_val
=
emitter
.
createCall
(
unw_info
,
g
.
funcs
.
getSysStdout
);
llvm
::
Value
*
sys_stdout_val
=
emitter
.
createCall
(
unw_info
,
g
.
funcs
.
getSysStdout
);
...
@@ -2012,63 +2022,22 @@ private:
...
@@ -2012,63 +2022,22 @@ private:
}
}
assert
(
dest
);
assert
(
dest
);
static
BoxedString
*
write_str
=
internStringImmortal
(
"write"
);
assert
(
node
->
values
.
size
()
<=
1
);
static
BoxedString
*
newline_str
=
internStringImmortal
(
"
\n
"
);
ConcreteCompilerVariable
*
converted
;
static
BoxedString
*
space_str
=
internStringImmortal
(
" "
);
// TODO: why are we inline-generating all this code instead of just emitting a call to some runtime function?
if
(
node
->
values
.
size
()
==
1
)
{
// (=printHelper())
CompilerVariable
*
var
=
evalExpr
(
node
->
values
[
0
],
unw_info
);
int
nvals
=
node
->
values
.
size
();
converted
=
var
->
makeConverted
(
emitter
,
var
->
getBoxType
());
for
(
int
i
=
0
;
i
<
nvals
;
i
++
)
{
CompilerVariable
*
var
=
evalExpr
(
node
->
values
[
i
],
unw_info
);
ConcreteCompilerVariable
*
converted
=
var
->
makeConverted
(
emitter
,
var
->
getBoxType
());
var
->
decvref
(
emitter
);
var
->
decvref
(
emitter
);
}
else
{
// begin code for handling of softspace
converted
=
new
ConcreteCompilerVariable
(
UNKNOWN
,
getNullPtr
(
g
.
llvm_value_type_ptr
),
true
);
bool
new_softspace
=
(
i
<
nvals
-
1
)
||
(
!
node
->
nl
);
llvm
::
Value
*
dospace
=
emitter
.
createCall
(
unw_info
,
g
.
funcs
.
softspace
,
{
dest
->
getValue
(),
getConstantInt
(
new_softspace
,
g
.
i1
)
});
assert
(
dospace
->
getType
()
==
g
.
i1
);
llvm
::
BasicBlock
*
ss_block
=
llvm
::
BasicBlock
::
Create
(
g
.
context
,
"softspace"
,
irstate
->
getLLVMFunction
());
llvm
::
BasicBlock
*
join_block
=
llvm
::
BasicBlock
::
Create
(
g
.
context
,
"print"
,
irstate
->
getLLVMFunction
());
emitter
.
getBuilder
()
->
CreateCondBr
(
dospace
,
ss_block
,
join_block
);
curblock
=
ss_block
;
emitter
.
getBuilder
()
->
SetInsertPoint
(
ss_block
);
CallattrFlags
flags
=
{.
cls_only
=
false
,
.
null_on_nonexistent
=
false
,
.
argspec
=
ArgPassSpec
(
1
)
};
auto
r
=
dest
->
callattr
(
emitter
,
getOpInfoForNode
(
node
,
unw_info
),
write_str
,
flags
,
{
makeStr
(
space_str
)
},
NULL
);
r
->
decvref
(
emitter
);
emitter
.
getBuilder
()
->
CreateBr
(
join_block
);
curblock
=
join_block
;
emitter
.
getBuilder
()
->
SetInsertPoint
(
join_block
);
// end code for handling of softspace
llvm
::
Value
*
v
=
emitter
.
createCall
(
unw_info
,
g
.
funcs
.
strOrUnicode
,
converted
->
getValue
());
v
=
emitter
.
getBuilder
()
->
CreateBitCast
(
v
,
g
.
llvm_value_type_ptr
);
auto
s
=
new
ConcreteCompilerVariable
(
STR
,
v
,
true
);
r
=
dest
->
callattr
(
emitter
,
getOpInfoForNode
(
node
,
unw_info
),
write_str
,
flags
,
{
s
},
NULL
);
s
->
decvref
(
emitter
);
r
->
decvref
(
emitter
);
converted
->
decvref
(
emitter
);
}
}
if
(
node
->
nl
)
{
emitter
.
createCall3
(
unw_info
,
g
.
funcs
.
printHelper
,
dest
->
getValue
(),
converted
->
getValue
(),
CallattrFlags
flags
=
{.
cls_only
=
false
,
.
null_on_nonexistent
=
false
,
.
argspec
=
ArgPassSpec
(
1
)
};
getConstantInt
(
node
->
nl
,
g
.
i1
));
auto
r
=
dest
->
callattr
(
emitter
,
getOpInfoForNode
(
node
,
unw_info
),
write_str
,
flags
,
{
makeStr
(
newline_str
)
},
NULL
);
r
->
decvref
(
emitter
);
if
(
nvals
==
0
)
{
emitter
.
createCall
(
unw_info
,
g
.
funcs
.
softspace
,
{
dest
->
getValue
(),
getConstantInt
(
0
,
g
.
i1
)
});
}
}
dest
->
decvref
(
emitter
);
dest
->
decvref
(
emitter
);
converted
->
decvref
(
emitter
);
}
}
void
doReturn
(
AST_Return
*
node
,
const
UnwindInfo
&
unw_info
)
{
void
doReturn
(
AST_Return
*
node
,
const
UnwindInfo
&
unw_info
)
{
...
...
src/codegen/irgen/util.cpp
View file @
bfbcc4b9
...
@@ -243,7 +243,7 @@ public:
...
@@ -243,7 +243,7 @@ public:
if
(
!
lookup_success
)
{
if
(
!
lookup_success
)
{
llvm
::
Constant
*
int_val
llvm
::
Constant
*
int_val
=
llvm
::
ConstantInt
::
get
(
g
.
i64
,
reinterpret_cast
<
uintptr_t
>
(
addr
),
false
);
=
llvm
::
ConstantInt
::
get
(
g
.
i64
,
reinterpret_cast
<
uintptr_t
>
(
addr
),
false
);
llvm
::
Constant
*
ptr_val
=
llvm
::
ConstantExpr
::
getIntToPtr
(
int_val
,
g
.
i8
);
llvm
::
Constant
*
ptr_val
=
llvm
::
ConstantExpr
::
getIntToPtr
(
int_val
,
g
.
i8
_ptr
);
ii
->
setArgOperand
(
i
,
ptr_val
);
ii
->
setArgOperand
(
i
,
ptr_val
);
continue
;
continue
;
}
else
{
}
else
{
...
...
src/codegen/runtime_hooks.cpp
View file @
bfbcc4b9
...
@@ -240,6 +240,7 @@ void initGlobalFuncs(GlobalState& g) {
...
@@ -240,6 +240,7 @@ void initGlobalFuncs(GlobalState& g) {
GET
(
assertFailDerefNameDefined
);
GET
(
assertFailDerefNameDefined
);
GET
(
assertFail
);
GET
(
assertFail
);
GET
(
printExprHelper
);
GET
(
printExprHelper
);
GET
(
printHelper
);
GET
(
printFloat
);
GET
(
printFloat
);
GET
(
listAppendInternal
);
GET
(
listAppendInternal
);
...
...
src/codegen/runtime_hooks.h
View file @
bfbcc4b9
...
@@ -42,7 +42,7 @@ struct GlobalFuncs {
...
@@ -42,7 +42,7 @@ struct GlobalFuncs {
llvm
::
Value
*
unpackIntoArray
,
*
raiseAttributeError
,
*
raiseAttributeErrorStr
,
*
raiseAttributeErrorCapi
,
llvm
::
Value
*
unpackIntoArray
,
*
raiseAttributeError
,
*
raiseAttributeErrorStr
,
*
raiseAttributeErrorCapi
,
*
raiseAttributeErrorStrCapi
,
*
raiseNotIterableError
,
*
raiseIndexErrorStr
,
*
raiseIndexErrorStrCapi
,
*
raiseAttributeErrorStrCapi
,
*
raiseNotIterableError
,
*
raiseIndexErrorStr
,
*
raiseIndexErrorStrCapi
,
*
assertNameDefined
,
*
assertFail
,
*
assertFailDerefNameDefined
,
*
printExprHelper
;
*
assertNameDefined
,
*
assertFail
,
*
assertFailDerefNameDefined
,
*
printExprHelper
,
*
printHelper
;
llvm
::
Value
*
printFloat
,
*
listAppendInternal
,
*
getSysStdout
;
llvm
::
Value
*
printFloat
,
*
listAppendInternal
,
*
getSysStdout
;
ExceptionSwitchable
<
llvm
::
Value
*>
runtimeCall0
,
runtimeCall1
,
runtimeCall2
,
runtimeCall3
,
runtimeCall
,
runtimeCallN
;
ExceptionSwitchable
<
llvm
::
Value
*>
runtimeCall0
,
runtimeCall1
,
runtimeCall2
,
runtimeCall3
,
runtimeCall
,
runtimeCallN
;
ExceptionSwitchable
<
llvm
::
Value
*>
callattr0
,
callattr1
,
callattr2
,
callattr3
,
callattr
,
callattrN
;
ExceptionSwitchable
<
llvm
::
Value
*>
callattr0
,
callattr1
,
callattr2
,
callattr3
,
callattr
,
callattrN
;
...
...
src/core/ast.cpp
View file @
bfbcc4b9
...
@@ -1056,6 +1056,7 @@ void* AST_MakeClass::accept_expr(ExprVisitor* v) {
...
@@ -1056,6 +1056,7 @@ void* AST_MakeClass::accept_expr(ExprVisitor* v) {
void
print_ast
(
AST
*
ast
)
{
void
print_ast
(
AST
*
ast
)
{
PrintVisitor
v
;
PrintVisitor
v
;
ast
->
accept
(
&
v
);
ast
->
accept
(
&
v
);
v
.
flush
();
}
}
void
PrintVisitor
::
printIndent
()
{
void
PrintVisitor
::
printIndent
()
{
...
...
src/core/ast.h
View file @
bfbcc4b9
...
@@ -1338,6 +1338,9 @@ private:
...
@@ -1338,6 +1338,9 @@ private:
public:
public:
PrintVisitor
(
int
indent
=
0
,
llvm
::
raw_ostream
&
stream
=
llvm
::
outs
())
:
stream
(
stream
),
indent
(
indent
)
{}
PrintVisitor
(
int
indent
=
0
,
llvm
::
raw_ostream
&
stream
=
llvm
::
outs
())
:
stream
(
stream
),
indent
(
indent
)
{}
virtual
~
PrintVisitor
()
{}
virtual
~
PrintVisitor
()
{}
void
flush
()
{
stream
.
flush
();
}
virtual
bool
visit_alias
(
AST_alias
*
node
);
virtual
bool
visit_alias
(
AST_alias
*
node
);
virtual
bool
visit_arguments
(
AST_arguments
*
node
);
virtual
bool
visit_arguments
(
AST_arguments
*
node
);
...
...
src/core/types.h
View file @
bfbcc4b9
...
@@ -527,10 +527,13 @@ public:
...
@@ -527,10 +527,13 @@ public:
llvm
::
iterator_range
<
BoxIterator
>
pyElements
();
llvm
::
iterator_range
<
BoxIterator
>
pyElements
();
// For instances with hc attrs:
size_t
getHCAttrsOffset
();
size_t
getHCAttrsOffset
();
HCAttrs
*
getHCAttrsPtr
();
HCAttrs
*
getHCAttrsPtr
();
void
setDict
(
BoxedDict
*
d
);
void
setDictBacked
(
Box
*
d
);
// For instances with dict attrs:
BoxedDict
*
getDict
();
BoxedDict
*
getDict
();
void
setDict
(
BoxedDict
*
d
);
void
setattr
(
BoxedString
*
attr
,
Box
*
val
,
SetattrRewriteArgs
*
rewrite_args
);
void
setattr
(
BoxedString
*
attr
,
Box
*
val
,
SetattrRewriteArgs
*
rewrite_args
);
...
...
src/gc/collector.cpp
View file @
bfbcc4b9
...
@@ -602,6 +602,7 @@ static void orderFinalizers() {
...
@@ -602,6 +602,7 @@ static void orderFinalizers() {
std
::
vector
<
Box
*>
finalizer_marked
;
std
::
vector
<
Box
*>
finalizer_marked
;
for
(
Box
*
obj
:
objects_with_ordered_finalizers
)
{
for
(
Box
*
obj
:
objects_with_ordered_finalizers
)
{
GC_TRACE_LOG
(
"%p has an ordered finalizer
\n
"
,
obj
);
GCAllocation
*
al
=
GCAllocation
::
fromUserData
(
obj
);
GCAllocation
*
al
=
GCAllocation
::
fromUserData
(
obj
);
// We are only interested in object with finalizers that need to be garbage-collected.
// We are only interested in object with finalizers that need to be garbage-collected.
...
@@ -920,9 +921,10 @@ static void openTraceFp(bool is_pre) {
...
@@ -920,9 +921,10 @@ static void openTraceFp(bool is_pre) {
fclose
(
trace_fp
);
fclose
(
trace_fp
);
char
tracefn_buf
[
80
];
char
tracefn_buf
[
80
];
snprintf
(
tracefn_buf
,
sizeof
(
tracefn_buf
),
"gc_trace_%d.%0
3
d%s.txt"
,
getpid
(),
ncollections
+
is_pre
,
snprintf
(
tracefn_buf
,
sizeof
(
tracefn_buf
),
"gc_trace_%d.%0
4
d%s.txt"
,
getpid
(),
ncollections
+
is_pre
,
is_pre
?
"_pre"
:
""
);
is_pre
?
"_pre"
:
""
);
trace_fp
=
fopen
(
tracefn_buf
,
"w"
);
trace_fp
=
fopen
(
tracefn_buf
,
"w"
);
assert
(
trace_fp
);
}
}
static
int
_dummy
()
{
static
int
_dummy
()
{
...
@@ -1001,17 +1003,29 @@ void runCollection() {
...
@@ -1001,17 +1003,29 @@ void runCollection() {
}
}
// We want to make sure that classes get freed before their metaclasses.
// We want to make sure that classes get freed before their metaclasses.
// Use a simple approach of only freeing one level of the hierarchy and then
// So, while there are still more classes to free, free any classes that are
// letting the next collection do the next one.
// not the metaclass of another class we will free. Then repeat.
llvm
::
DenseSet
<
BoxedClass
*>
classes_to_not_free
;
//
for
(
auto
b
:
classes_to_free
)
{
// Note: our earlier approach of just deferring metaclasses to the next collection is
classes_to_not_free
.
insert
(
b
->
cls
);
// not quite safe, since we will have freed everything that the class refers to.
}
while
(
!
classes_to_free
.
empty
())
{
llvm
::
DenseSet
<
BoxedClass
*>
classes_to_not_free
;
for
(
auto
b
:
classes_to_free
)
{
classes_to_not_free
.
insert
(
b
->
cls
);
}
std
::
vector
<
BoxedClass
*>
deferred_classes
;
for
(
auto
b
:
classes_to_free
)
{
GC_TRACE_LOG
(
"Dealing with the postponed free of class %p
\n
"
,
b
);
if
(
classes_to_not_free
.
count
(
b
))
{
deferred_classes
.
push_back
(
b
);
continue
;
}
global_heap
.
_setFree
(
GCAllocation
::
fromUserData
(
b
));
}
for
(
auto
b
:
classes_to_free
)
{
assert
(
deferred_classes
.
size
()
<
classes_to_free
.
size
());
if
(
classes_to_not_free
.
count
(
b
))
std
::
swap
(
deferred_classes
,
classes_to_free
);
continue
;
global_heap
.
_setFree
(
GCAllocation
::
fromUserData
(
b
));
}
}
global_heap
.
cleanupAfterCollection
();
global_heap
.
cleanupAfterCollection
();
...
...
src/gc/gc.h
View file @
bfbcc4b9
...
@@ -28,14 +28,6 @@
...
@@ -28,14 +28,6 @@
#define GC_KEEP_ALIVE(t) asm volatile("" : : "X"(t))
#define GC_KEEP_ALIVE(t) asm volatile("" : : "X"(t))
#define TRACE_GC_MARKING 0
#if TRACE_GC_MARKING
extern
FILE
*
trace_fp
;
#define GC_TRACE_LOG(...) fprintf(pyston::gc::trace_fp, __VA_ARGS__)
#else
#define GC_TRACE_LOG(...)
#endif
struct
_PyWeakReference
;
struct
_PyWeakReference
;
typedef
struct
_PyWeakReference
PyWeakReference
;
typedef
struct
_PyWeakReference
PyWeakReference
;
...
@@ -45,6 +37,14 @@ class Box;
...
@@ -45,6 +37,14 @@ class Box;
namespace
gc
{
namespace
gc
{
class
GCVisitable
;
class
GCVisitable
;
#define TRACE_GC_MARKING 0
#if TRACE_GC_MARKING
extern
FILE
*
trace_fp
;
#define GC_TRACE_LOG(...) fprintf(pyston::gc::trace_fp, __VA_ARGS__)
#else
#define GC_TRACE_LOG(...)
#endif
}
}
namespace
threading
{
namespace
threading
{
...
...
src/gc/gc_alloc.h
View file @
bfbcc4b9
...
@@ -112,8 +112,6 @@ extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
...
@@ -112,8 +112,6 @@ extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
// if (VERBOSITY()) printf("Allocated %ld bytes at [%p, %p)\n", bytes, r, (char*)r + bytes);
// if (VERBOSITY()) printf("Allocated %ld bytes at [%p, %p)\n", bytes, r, (char*)r + bytes);
#endif
#endif
GC_TRACE_LOG
(
"Allocated %p
\n
"
,
r
);
#if STAT_ALLOCATIONS
#if STAT_ALLOCATIONS
gc_alloc_bytes
.
log
(
alloc_bytes
);
gc_alloc_bytes
.
log
(
alloc_bytes
);
gc_alloc_bytes_typed
[(
int
)
kind_id
].
log
(
alloc_bytes
);
gc_alloc_bytes_typed
[(
int
)
kind_id
].
log
(
alloc_bytes
);
...
...
src/gc/heap.cpp
View file @
bfbcc4b9
...
@@ -186,7 +186,7 @@ __attribute__((always_inline)) bool _doFree(GCAllocation* al, std::vector<Box*>*
...
@@ -186,7 +186,7 @@ __attribute__((always_inline)) bool _doFree(GCAllocation* al, std::vector<Box*>*
if
(
unlikely
(
isWeaklyReferenced
(
b
)))
{
if
(
unlikely
(
isWeaklyReferenced
(
b
)))
{
assert
(
weakly_referenced
&&
"attempting to free a weakly referenced object manually"
);
assert
(
weakly_referenced
&&
"attempting to free a weakly referenced object manually"
);
weakly_referenced
->
push_back
(
b
);
weakly_referenced
->
push_back
(
b
);
GC_TRACE_LOG
(
"%p is weakly referenced
\n
"
,
al
->
user_data
);
GC_TRACE_LOG
(
"
doFree:
%p is weakly referenced
\n
"
,
al
->
user_data
);
return
false
;
return
false
;
}
}
...
@@ -196,11 +196,12 @@ __attribute__((always_inline)) bool _doFree(GCAllocation* al, std::vector<Box*>*
...
@@ -196,11 +196,12 @@ __attribute__((always_inline)) bool _doFree(GCAllocation* al, std::vector<Box*>*
if
(
unlikely
(
PyType_Check
(
b
)))
{
if
(
unlikely
(
PyType_Check
(
b
)))
{
assert
(
classes_to_free
);
assert
(
classes_to_free
);
classes_to_free
->
push_back
(
static_cast
<
BoxedClass
*>
(
b
));
classes_to_free
->
push_back
(
static_cast
<
BoxedClass
*>
(
b
));
GC_TRACE_LOG
(
"doFree: %p is a class object
\n
"
,
al
->
user_data
);
return
false
;
return
false
;
}
}
if
(
b
->
cls
->
tp_dealloc
!=
dealloc_null
&&
b
->
cls
->
has_safe_tp_dealloc
)
{
if
(
b
->
cls
->
tp_dealloc
!=
dealloc_null
&&
b
->
cls
->
has_safe_tp_dealloc
)
{
GC_TRACE_LOG
(
"running safe destructor for %p
\n
"
,
b
);
GC_TRACE_LOG
(
"
doFree:
running safe destructor for %p
\n
"
,
b
);
gc_safe_destructors
.
log
();
gc_safe_destructors
.
log
();
GCAllocation
*
al
=
GCAllocation
::
fromUserData
(
b
);
GCAllocation
*
al
=
GCAllocation
::
fromUserData
(
b
);
...
@@ -687,8 +688,10 @@ GCAllocation* SmallArena::_alloc(size_t rounded_size, int bucket_idx) {
...
@@ -687,8 +688,10 @@ GCAllocation* SmallArena::_alloc(size_t rounded_size, int bucket_idx) {
while
(
true
)
{
while
(
true
)
{
while
(
Block
*
cache_block
=
*
cache_head
)
{
while
(
Block
*
cache_block
=
*
cache_head
)
{
GCAllocation
*
rtn
=
_allocFromBlock
(
cache_block
);
GCAllocation
*
rtn
=
_allocFromBlock
(
cache_block
);
if
(
rtn
)
if
(
rtn
)
{
GC_TRACE_LOG
(
"Allocated %p
\n
"
,
rtn
->
user_data
);
return
rtn
;
return
rtn
;
}
removeFromLLAndNull
(
cache_block
);
removeFromLLAndNull
(
cache_block
);
insertIntoLL
(
&
cache
->
cache_full_heads
[
bucket_idx
],
cache_block
);
insertIntoLL
(
&
cache
->
cache_full_heads
[
bucket_idx
],
cache_block
);
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
bfbcc4b9
...
@@ -598,7 +598,7 @@ Box* setattrFunc(Box* obj, Box* _str, Box* value) {
...
@@ -598,7 +598,7 @@ Box* setattrFunc(Box* obj, Box* _str, Box* value) {
_str
=
coerceUnicodeToStr
<
CXX
>
(
_str
);
_str
=
coerceUnicodeToStr
<
CXX
>
(
_str
);
if
(
_str
->
cls
!=
str_cls
)
{
if
(
_str
->
cls
!=
str_cls
)
{
raiseExcHelper
(
TypeError
,
"
setattr(): attribute name must be string"
);
raiseExcHelper
(
TypeError
,
"
attribute name must be string, not '%s'"
,
_str
->
cls
->
tp_name
);
}
}
BoxedString
*
str
=
static_cast
<
BoxedString
*>
(
_str
);
BoxedString
*
str
=
static_cast
<
BoxedString
*>
(
_str
);
...
...
src/runtime/inline/link_forcer.cpp
View file @
bfbcc4b9
...
@@ -113,6 +113,7 @@ void force() {
...
@@ -113,6 +113,7 @@ void force() {
FORCE
(
assertFailDerefNameDefined
);
FORCE
(
assertFailDerefNameDefined
);
FORCE
(
assertFail
);
FORCE
(
assertFail
);
FORCE
(
printExprHelper
);
FORCE
(
printExprHelper
);
FORCE
(
printHelper
);
FORCE
(
strOrUnicode
);
FORCE
(
strOrUnicode
);
FORCE
(
printFloat
);
FORCE
(
printFloat
);
...
...
src/runtime/list.cpp
View file @
bfbcc4b9
...
@@ -1282,6 +1282,7 @@ void setupList() {
...
@@ -1282,6 +1282,7 @@ void setupList() {
sizeof
(
BoxedListIterator
),
false
,
"listiterator"
);
sizeof
(
BoxedListIterator
),
false
,
"listiterator"
);
list_reverse_iterator_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedListIterator
::
gcHandler
,
0
,
0
,
list_reverse_iterator_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedListIterator
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedListIterator
),
false
,
"listreverseiterator"
);
sizeof
(
BoxedListIterator
),
false
,
"listreverseiterator"
);
list_iterator_cls
->
instances_are_nonzero
=
list_reverse_iterator_cls
->
instances_are_nonzero
=
true
;
list_cls
->
giveAttr
(
"__len__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
listLen
,
BOXED_INT
,
1
)));
list_cls
->
giveAttr
(
"__len__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
listLen
,
BOXED_INT
,
1
)));
...
...
src/runtime/objmodel.cpp
View file @
bfbcc4b9
...
@@ -222,6 +222,9 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) {
...
@@ -222,6 +222,9 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) {
static
BoxedString
*
newline_str
=
internStringImmortal
(
"
\n
"
);
static
BoxedString
*
newline_str
=
internStringImmortal
(
"
\n
"
);
static
BoxedString
*
space_str
=
internStringImmortal
(
" "
);
static
BoxedString
*
space_str
=
internStringImmortal
(
" "
);
if
(
dest
==
None
)
dest
=
getSysStdout
();
if
(
var
)
{
if
(
var
)
{
// begin code for handling of softspace
// begin code for handling of softspace
bool
new_softspace
=
!
nl
;
bool
new_softspace
=
!
nl
;
...
@@ -229,11 +232,17 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) {
...
@@ -229,11 +232,17 @@ extern "C" void printHelper(Box* dest, Box* var, bool nl) {
callattrInternal
<
CXX
>
(
dest
,
write_str
,
CLASS_OR_INST
,
0
,
ArgPassSpec
(
1
),
space_str
,
0
,
0
,
0
,
0
);
callattrInternal
<
CXX
>
(
dest
,
write_str
,
CLASS_OR_INST
,
0
,
ArgPassSpec
(
1
),
space_str
,
0
,
0
,
0
,
0
);
Box
*
str_or_unicode_var
=
(
var
->
cls
==
unicode_cls
)
?
var
:
str
(
var
);
Box
*
str_or_unicode_var
=
(
var
->
cls
==
unicode_cls
)
?
var
:
str
(
var
);
callattrInternal
<
CXX
>
(
dest
,
write_str
,
CLASS_OR_INST
,
0
,
ArgPassSpec
(
1
),
str_or_unicode_var
,
0
,
0
,
0
,
0
);
Box
*
write_rtn
=
callattrInternal
<
CXX
>
(
dest
,
write_str
,
CLASS_OR_INST
,
0
,
ArgPassSpec
(
1
),
str_or_unicode_var
,
0
,
0
,
0
,
0
);
if
(
!
write_rtn
)
raiseAttributeError
(
dest
,
write_str
->
s
());
}
}
if
(
nl
)
{
if
(
nl
)
{
callattrInternal
<
CXX
>
(
dest
,
write_str
,
CLASS_OR_INST
,
0
,
ArgPassSpec
(
1
),
newline_str
,
0
,
0
,
0
,
0
);
Box
*
write_rtn
=
callattrInternal
<
CXX
>
(
dest
,
write_str
,
CLASS_OR_INST
,
0
,
ArgPassSpec
(
1
),
newline_str
,
0
,
0
,
0
,
0
);
if
(
!
write_rtn
)
raiseAttributeError
(
dest
,
write_str
->
s
());
if
(
!
var
)
if
(
!
var
)
softspace
(
dest
,
false
);
softspace
(
dest
,
false
);
}
}
...
@@ -996,12 +1005,10 @@ Box* typeLookup(BoxedClass* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_
...
@@ -996,12 +1005,10 @@ Box* typeLookup(BoxedClass* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_
rewrite_args
->
obj_shape_guarded
=
true
;
rewrite_args
->
obj_shape_guarded
=
true
;
}
}
val
=
base
->
getattr
(
attr
,
rewrite_args
);
val
=
base
->
getattr
(
attr
,
rewrite_args
);
assert
(
rewrite_args
->
out_success
);
if
(
val
)
if
(
val
)
return
val
;
return
val
;
}
}
assert
(
rewrite_args
->
out_success
);
assert
(
!
rewrite_args
->
out_rtn
);
assert
(
!
rewrite_args
->
out_rtn
);
rewrite_args
->
out_return_convention
=
GetattrRewriteArgs
::
NO_RETURN
;
rewrite_args
->
out_return_convention
=
GetattrRewriteArgs
::
NO_RETURN
;
return
NULL
;
return
NULL
;
...
@@ -2486,12 +2493,13 @@ extern "C" bool nonzero(Box* obj) {
...
@@ -2486,12 +2493,13 @@ extern "C" bool nonzero(Box* obj) {
rewriter
.
reset
();
rewriter
.
reset
();
if
(
rtn
==
NULL
)
{
if
(
rtn
==
NULL
)
{
ASSERT
(
obj
->
cls
->
is_user_defined
||
obj
->
cls
==
classobj_cls
||
obj
->
cls
==
type_cls
ASSERT
(
obj
->
cls
->
is_user_defined
||
obj
->
cls
->
instances_are_nonzero
||
obj
->
cls
==
classobj_cls
||
isSubclass
(
obj
->
cls
,
Exception
)
||
obj
->
cls
==
file_cls
||
obj
->
cls
==
traceback_cls
||
obj
->
cls
==
type_cls
||
isSubclass
(
obj
->
cls
,
Exception
)
||
obj
->
cls
==
file_cls
||
obj
->
cls
==
instancemethod_cls
||
obj
->
cls
==
module_cls
||
obj
->
cls
==
capifunc_cls
||
obj
->
cls
==
traceback_cls
||
obj
->
cls
==
instancemethod_cls
||
obj
->
cls
==
module_cls
||
obj
->
cls
==
builtin_function_or_method_cls
||
obj
->
cls
==
method_cls
||
obj
->
cls
==
frame_cls
||
obj
->
cls
==
capifunc_cls
||
obj
->
cls
==
builtin_function_or_method_cls
||
obj
->
cls
==
generator_cls
||
obj
->
cls
==
capi_getset_cls
||
obj
->
cls
==
pyston_getset_cls
||
obj
->
cls
==
method_cls
||
obj
->
cls
==
frame_cls
||
obj
->
cls
==
generator_cls
||
obj
->
cls
==
wrapperdescr_cls
||
obj
->
cls
==
wrapperobject_cls
,
||
obj
->
cls
==
capi_getset_cls
||
obj
->
cls
==
pyston_getset_cls
||
obj
->
cls
==
wrapperdescr_cls
||
obj
->
cls
==
wrapperobject_cls
,
"%s.__nonzero__"
,
getTypeName
(
obj
));
// TODO
"%s.__nonzero__"
,
getTypeName
(
obj
));
// TODO
if
(
rewriter
.
get
())
{
if
(
rewriter
.
get
())
{
...
...
src/runtime/types.cpp
View file @
bfbcc4b9
...
@@ -1398,6 +1398,20 @@ static Box* typeSubDict(Box* obj, void* context) {
...
@@ -1398,6 +1398,20 @@ static Box* typeSubDict(Box* obj, void* context) {
abort
();
abort
();
}
}
void
Box
::
setDictBacked
(
Box
*
val
)
{
assert
(
this
->
cls
->
instancesHaveHCAttrs
());
RELEASE_ASSERT
(
val
->
cls
==
dict_cls
||
val
->
cls
==
attrwrapper_cls
,
""
);
auto
new_attr_list
=
(
HCAttrs
::
AttrList
*
)
gc_alloc
(
sizeof
(
HCAttrs
::
AttrList
)
+
sizeof
(
Box
*
),
gc
::
GCKind
::
PRECISE
);
new_attr_list
->
attrs
[
0
]
=
val
;
HCAttrs
*
hcattrs
=
this
->
getHCAttrsPtr
();
hcattrs
->
hcls
=
HiddenClass
::
dict_backed
;
hcattrs
->
attr_list
=
new_attr_list
;
}
static
void
typeSubSetDict
(
Box
*
obj
,
Box
*
val
,
void
*
context
)
{
static
void
typeSubSetDict
(
Box
*
obj
,
Box
*
val
,
void
*
context
)
{
if
(
obj
->
cls
->
instancesHaveDictAttrs
())
{
if
(
obj
->
cls
->
instancesHaveDictAttrs
())
{
RELEASE_ASSERT
(
val
->
cls
==
dict_cls
,
""
);
RELEASE_ASSERT
(
val
->
cls
==
dict_cls
,
""
);
...
@@ -1406,16 +1420,7 @@ static void typeSubSetDict(Box* obj, Box* val, void* context) {
...
@@ -1406,16 +1420,7 @@ static void typeSubSetDict(Box* obj, Box* val, void* context) {
}
}
if
(
obj
->
cls
->
instancesHaveHCAttrs
())
{
if
(
obj
->
cls
->
instancesHaveHCAttrs
())
{
RELEASE_ASSERT
(
val
->
cls
==
dict_cls
||
val
->
cls
==
attrwrapper_cls
,
""
);
obj
->
setDictBacked
(
val
);
auto
new_attr_list
=
(
HCAttrs
::
AttrList
*
)
gc_alloc
(
sizeof
(
HCAttrs
::
AttrList
)
+
sizeof
(
Box
*
),
gc
::
GCKind
::
PRECISE
);
new_attr_list
->
attrs
[
0
]
=
val
;
HCAttrs
*
hcattrs
=
obj
->
getHCAttrsPtr
();
hcattrs
->
hcls
=
HiddenClass
::
dict_backed
;
hcattrs
->
attr_list
=
new_attr_list
;
return
;
return
;
}
}
...
@@ -2218,6 +2223,28 @@ class AttrWrapper : public Box {
...
@@ -2218,6 +2223,28 @@ class AttrWrapper : public Box {
private:
private:
Box
*
b
;
Box
*
b
;
void
convertToDictBacked
()
{
HCAttrs
*
attrs
=
this
->
b
->
getHCAttrsPtr
();
if
(
attrs
->
hcls
->
type
==
HiddenClass
::
DICT_BACKED
)
return
;
BoxedDict
*
d
=
new
BoxedDict
();
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
attrs
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
d
->
d
[
p
.
first
]
=
attrs
->
attr_list
->
attrs
[
p
.
second
];
}
b
->
setDictBacked
(
d
);
}
bool
isDictBacked
()
{
return
b
->
getHCAttrsPtr
()
->
hcls
->
type
==
HiddenClass
::
DICT_BACKED
;
}
Box
*
getDictBacking
()
{
assert
(
isDictBacked
());
return
b
->
getHCAttrsPtr
()
->
attr_list
->
attrs
[
0
];
}
public:
public:
AttrWrapper
(
Box
*
b
)
:
b
(
b
)
{
AttrWrapper
(
Box
*
b
)
:
b
(
b
)
{
assert
(
b
->
cls
->
instancesHaveHCAttrs
());
assert
(
b
->
cls
->
instancesHaveHCAttrs
());
...
@@ -2246,9 +2273,16 @@ public:
...
@@ -2246,9 +2273,16 @@ public:
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
if
(
_key
->
cls
!=
str_cls
)
self
->
convertToDictBacked
();
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
""
);
if
(
self
->
isDictBacked
())
{
static
BoxedString
*
setitem_str
=
internStringImmortal
(
"__setitem__"
);
return
callattrInternal
<
CXX
>
(
self
->
getDictBacking
(),
setitem_str
,
LookupScope
::
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
2
),
_key
,
value
,
NULL
,
NULL
,
NULL
);
}
assert
(
_key
->
cls
==
str_cls
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
internStringMortalInplace
(
key
);
internStringMortalInplace
(
key
);
...
@@ -2276,9 +2310,16 @@ public:
...
@@ -2276,9 +2310,16 @@ public:
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
if
(
_key
->
cls
!=
str_cls
)
self
->
convertToDictBacked
();
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
""
);
if
(
self
->
isDictBacked
())
{
static
BoxedString
*
setdefault_str
=
internStringImmortal
(
"setdefault"
);
return
callattrInternal
<
CXX
>
(
self
->
getDictBacking
(),
setdefault_str
,
LookupScope
::
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
2
),
_key
,
value
,
NULL
,
NULL
,
NULL
);
}
assert
(
_key
->
cls
==
str_cls
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
internStringMortalInplace
(
key
);
internStringMortalInplace
(
key
);
...
@@ -2313,7 +2354,7 @@ public:
...
@@ -2313,7 +2354,7 @@ public:
if
(
S
==
CAPI
&&
!
_key
)
if
(
S
==
CAPI
&&
!
_key
)
return
NULL
;
return
NULL
;
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
"
%s"
,
_key
->
cls
->
tp_name
);
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
"
"
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
internStringMortalInplace
(
key
);
internStringMortalInplace
(
key
);
...
@@ -2354,7 +2395,7 @@ public:
...
@@ -2354,7 +2395,7 @@ public:
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
_key
=
coerceUnicodeToStr
<
CXX
>
(
_key
);
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
"
%s"
,
_key
->
cls
->
tp_name
);
RELEASE_ASSERT
(
_key
->
cls
==
str_cls
,
"
"
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
BoxedString
*
key
=
static_cast
<
BoxedString
*>
(
_key
);
internStringMortalInplace
(
key
);
internStringMortalInplace
(
key
);
...
@@ -2559,6 +2600,12 @@ public:
...
@@ -2559,6 +2600,12 @@ public:
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapper_cls
,
""
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
if
(
self
->
isDictBacked
())
{
static
BoxedString
*
iter_str
=
internStringImmortal
(
"__iter__"
);
return
callattrInternal
<
CXX
>
(
self
->
getDictBacking
(),
iter_str
,
LookupScope
::
CLASS_ONLY
,
NULL
,
ArgPassSpec
(
0
),
NULL
,
NULL
,
NULL
,
NULL
,
NULL
);
}
return
new
AttrWrapperIter
(
self
);
return
new
AttrWrapperIter
(
self
);
}
}
...
@@ -3505,6 +3552,7 @@ void setupRuntime() {
...
@@ -3505,6 +3552,7 @@ void setupRuntime() {
// XXX silly that we have to set this again
// XXX silly that we have to set this again
new
(
&
object_cls
->
attrs
)
HCAttrs
(
HiddenClass
::
makeSingleton
());
new
(
&
object_cls
->
attrs
)
HCAttrs
(
HiddenClass
::
makeSingleton
());
new
(
&
type_cls
->
attrs
)
HCAttrs
(
HiddenClass
::
makeSingleton
());
new
(
&
type_cls
->
attrs
)
HCAttrs
(
HiddenClass
::
makeSingleton
());
object_cls
->
instances_are_nonzero
=
true
;
object_cls
->
tp_getattro
=
PyObject_GenericGetAttr
;
object_cls
->
tp_getattro
=
PyObject_GenericGetAttr
;
object_cls
->
tp_setattro
=
PyObject_GenericSetAttr
;
object_cls
->
tp_setattro
=
PyObject_GenericSetAttr
;
object_cls
->
tp_init
=
object_init
;
object_cls
->
tp_init
=
object_init
;
...
...
src/runtime/types.h
View file @
bfbcc4b9
...
@@ -235,6 +235,12 @@ public:
...
@@ -235,6 +235,12 @@ public:
// that we can't rely on for extension classes.
// that we can't rely on for extension classes.
bool
is_pyston_class
;
bool
is_pyston_class
;
// Just for debugging: whether instances of this class should always be considered nonzero.
// This is the default for anything that doesn't define a __nonzero__ or __len__ method, but
// for builtin types we have the extra check that we opted into this behavior rather than
// just forgot to add nonzero/len.
bool
instances_are_nonzero
;
bool
has___class__
;
// Has a custom __class__ attribute (ie different from object's __class__ descriptor)
bool
has___class__
;
// Has a custom __class__ attribute (ie different from object's __class__ descriptor)
bool
has_instancecheck
;
bool
has_instancecheck
;
bool
has_subclasscheck
;
bool
has_subclasscheck
;
...
...
test/integration/sqlalchemy_smalltest.py
View file @
bfbcc4b9
...
@@ -73,6 +73,7 @@ MODULES_TO_TEST = [
...
@@ -73,6 +73,7 @@ MODULES_TO_TEST = [
'test.base.test_events'
,
'test.base.test_events'
,
'test.base.test_except'
,
'test.base.test_except'
,
'test.base.test_inspect'
,
'test.base.test_inspect'
,
'test.base.test_utils'
,
'test.dialect.test_mxodbc'
,
'test.dialect.test_mxodbc'
,
'test.dialect.test_pyodbc'
,
'test.dialect.test_pyodbc'
,
'test.dialect.test_sybase'
,
'test.dialect.test_sybase'
,
...
@@ -103,7 +104,7 @@ for fn in test_files:
...
@@ -103,7 +104,7 @@ for fn in test_files:
m
=
__import__
(
mname
,
fromlist
=
[
"__all__"
])
m
=
__import__
(
mname
,
fromlist
=
[
"__all__"
])
for
clsname
in
dir
(
m
):
for
clsname
in
dir
(
m
):
cls
=
getattr
(
m
,
clsname
)
cls
=
getattr
(
m
,
clsname
)
if
not
clsname
.
endswith
(
"Test"
)
or
not
isinstance
(
cls
,
type
):
if
clsname
.
startswith
(
'_'
)
or
not
clsname
.
endswith
(
"Test"
)
or
not
isinstance
(
cls
,
type
):
continue
continue
print
"Running"
,
cls
print
"Running"
,
cls
...
...
test/tests/closure_test.py
View file @
bfbcc4b9
...
@@ -82,3 +82,15 @@ def f7(n):
...
@@ -82,3 +82,15 @@ def f7(n):
c
=
f7
(
5
)()
c
=
f7
(
5
)()
print
c
.
foo
()
print
c
.
foo
()
# Regression test: being included in a closure (ie in the parent scope) shouldn't ruin type analysis.
def
f8
():
l
=
[]
def
g
():
print
l
l
.
append
(
1
)
for
i
in
xrange
(
11000
):
f8
()
test/tests/dir.py
View file @
bfbcc4b9
...
@@ -123,3 +123,24 @@ while True:
...
@@ -123,3 +123,24 @@ while True:
except
StopIteration
:
except
StopIteration
:
break
break
print
sorted
(
l
)
print
sorted
(
l
)
c
=
C1
()
print
sorted
(
c
.
__dict__
.
items
())
# setattr() converts the attr name to a string:
setattr
(
c
,
u'a'
,
1
)
print
sorted
(
c
.
__dict__
.
items
())
# directly setting on the dict does not:
c
.
__dict__
[
u'b'
]
=
2
print
sorted
(
c
.
__dict__
.
items
())
c
.
__dict__
.
update
({
u'c'
:
3
})
print
sorted
(
c
.
__dict__
.
items
())
# Can't set non-string-attrs with setattr, but can via dict:
try
:
setattr
(
c
,
1
,
1
)
assert
0
except
TypeError
as
e
:
print
e
print
sorted
(
c
.
__dict__
.
items
())
c
.
__dict__
[
5
]
=
2
print
sorted
(
c
.
__dict__
.
items
())
test/tests/hasattr_guarding.py
0 → 100644
View file @
bfbcc4b9
# Test some weird hasattr guarding scenarios
# I think this applies equally well to getattr
def
f
(
o
):
print
hasattr
(
o
,
"a"
)
print
getattr
(
o
,
"a"
,
None
)
class
C
(
object
):
def
__getattr__
(
self
,
key
):
print
"getattr"
,
key
raise
AttributeError
(
key
)
for
i
in
xrange
(
300
):
print
i
c
=
C
()
try
:
f
(
c
)
except
AttributeError
as
e
:
print
e
c
.
a
=
1
setattr
(
c
,
str
(
i
),
i
)
f
(
c
)
test/tests/print.py
View file @
bfbcc4b9
...
@@ -54,3 +54,9 @@ try:
...
@@ -54,3 +54,9 @@ try:
assert
0
,
"expected TypeError was not thrown"
assert
0
,
"expected TypeError was not thrown"
except
TypeError
:
except
TypeError
:
pass
pass
print
>>
None
,
"this should still print"
try
:
print
>>
1
,
"this should error"
except
AttributeError
as
e
:
print
e
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