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
933834be
Commit
933834be
authored
May 08, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #510 from kmod/singleton_hcls
Singleton hcls storage strategy
parents
9030ec59
4ca839f9
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
156 additions
and
70 deletions
+156
-70
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+6
-5
src/core/types.h
src/core/types.h
+3
-6
src/gc/heap.cpp
src/gc/heap.cpp
+5
-1
src/runtime/dict.cpp
src/runtime/dict.cpp
+10
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+84
-35
src/runtime/types.cpp
src/runtime/types.cpp
+25
-14
src/runtime/types.h
src/runtime/types.h
+23
-8
No files found.
src/capi/typeobject.cpp
View file @
933834be
...
@@ -2717,13 +2717,14 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
...
@@ -2717,13 +2717,14 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
RELEASE_ASSERT
(
cls
->
tp_del
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_del
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_version_tag
==
0
,
""
);
RELEASE_ASSERT
(
cls
->
tp_version_tag
==
0
,
""
);
// I think it is safe to ignore these for for now:
// I think it is safe to ignore these for for now:
// RELEASE_ASSERT(cls->tp_weaklistoffset == 0, "");
// RELEASE_ASSERT(cls->tp_weaklistoffset == 0, "");
// RELEASE_ASSERT(cls->tp_traverse == NULL, "");
// RELEASE_ASSERT(cls->tp_traverse == NULL, "");
// RELEASE_ASSERT(cls->tp_clear == NULL, "");
// RELEASE_ASSERT(cls->tp_clear == NULL, "");
assert
(
cls
->
attrs
.
hcls
==
NULL
);
new
(
&
cls
->
attrs
)
HCAttrs
(
HiddenClass
::
makeSingleton
());
#define INITIALIZE(a) new (&(a)) decltype(a)
#define INITIALIZE(a) new (&(a)) decltype(a)
INITIALIZE
(
cls
->
attrs
);
INITIALIZE
(
cls
->
dependent_icgetattrs
);
INITIALIZE
(
cls
->
dependent_icgetattrs
);
#undef INITIALIZE
#undef INITIALIZE
...
...
src/core/types.h
View file @
933834be
...
@@ -418,7 +418,7 @@ public:
...
@@ -418,7 +418,7 @@ public:
HiddenClass
*
hcls
;
HiddenClass
*
hcls
;
AttrList
*
attr_list
;
AttrList
*
attr_list
;
HCAttrs
(
)
:
hcls
(
root_
hcls
),
attr_list
(
nullptr
)
{}
HCAttrs
(
HiddenClass
*
hcls
=
root_hcls
)
:
hcls
(
hcls
),
attr_list
(
nullptr
)
{}
};
};
class
BoxedDict
;
class
BoxedDict
;
...
@@ -428,11 +428,8 @@ class Box {
...
@@ -428,11 +428,8 @@ class Box {
private:
private:
BoxedDict
**
getDictPtr
();
BoxedDict
**
getDictPtr
();
// Adds a new attribute to a HCAttrs-backed object. Must pass in the new hidden class object
// Appends a new value to the hcattrs array.
// which must be the same as the current hidden class but with the new attribute at the end.
void
appendNewHCAttr
(
Box
*
val
,
SetattrRewriteArgs
*
rewrite_args
);
// Swaps the hidden class, reallocates and copies and updates the attribute array.
// The value of the current hidden class should be guarded before calling this.
void
addNewHCAttr
(
HiddenClass
*
new_hcls
,
Box
*
val
,
SetattrRewriteArgs
*
rewrite_args
);
public:
public:
// Add a no-op constructor to make sure that we don't zero-initialize cls
// Add a no-op constructor to make sure that we don't zero-initialize cls
...
...
src/gc/heap.cpp
View file @
933834be
...
@@ -208,7 +208,7 @@ struct HeapStatistics {
...
@@ -208,7 +208,7 @@ struct HeapStatistics {
TypeStats
total
;
TypeStats
total
;
HeapStatistics
(
bool
collect_cls_stats
,
bool
collect_hcls_stats
)
HeapStatistics
(
bool
collect_cls_stats
,
bool
collect_hcls_stats
)
:
collect_cls_stats
(
collect_cls_stats
),
collect_hcls_stats
(
collect_hcls_stats
)
{
:
collect_cls_stats
(
collect_cls_stats
),
collect_hcls_stats
(
collect_hcls_stats
)
,
num_hcls_by_attrs_exceed
(
0
)
{
memset
(
num_hcls_by_attrs
,
0
,
sizeof
(
num_hcls_by_attrs
));
memset
(
num_hcls_by_attrs
,
0
,
sizeof
(
num_hcls_by_attrs
));
}
}
};
};
...
@@ -233,6 +233,10 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
...
@@ -233,6 +233,10 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
Box
*
b
=
(
Box
*
)
al
->
user_data
;
Box
*
b
=
(
Box
*
)
al
->
user_data
;
if
(
b
->
cls
->
instancesHaveHCAttrs
())
{
if
(
b
->
cls
->
instancesHaveHCAttrs
())
{
HCAttrs
*
attrs
=
b
->
getHCAttrsPtr
();
HCAttrs
*
attrs
=
b
->
getHCAttrsPtr
();
if
(
attrs
->
hcls
->
attributeArraySize
()
>=
20
)
{
printf
(
"%s object has %d attributes
\n
"
,
b
->
cls
->
tp_name
,
attrs
->
hcls
->
attributeArraySize
());
}
stats
->
hcls_uses
[
attrs
->
hcls
]
++
;
stats
->
hcls_uses
[
attrs
->
hcls
]
++
;
}
}
}
}
...
...
src/runtime/dict.cpp
View file @
933834be
...
@@ -228,7 +228,6 @@ extern "C" int PyDict_SetItem(PyObject* mp, PyObject* _key, PyObject* _item) noe
...
@@ -228,7 +228,6 @@ extern "C" int PyDict_SetItem(PyObject* mp, PyObject* _key, PyObject* _item) noe
Box
*
item
=
static_cast
<
Box
*>
(
_item
);
Box
*
item
=
static_cast
<
Box
*>
(
_item
);
try
{
try
{
// TODO should demote GIL?
setitem
(
b
,
key
,
item
);
setitem
(
b
,
key
,
item
);
}
catch
(
ExcInfo
e
)
{
}
catch
(
ExcInfo
e
)
{
abort
();
abort
();
...
@@ -249,6 +248,16 @@ extern "C" int PyDict_SetItemString(PyObject* mp, const char* key, PyObject* ite
...
@@ -249,6 +248,16 @@ extern "C" int PyDict_SetItemString(PyObject* mp, const char* key, PyObject* ite
extern
"C"
PyObject
*
PyDict_GetItem
(
PyObject
*
dict
,
PyObject
*
key
)
noexcept
{
extern
"C"
PyObject
*
PyDict_GetItem
(
PyObject
*
dict
,
PyObject
*
key
)
noexcept
{
ASSERT
(
isSubclass
(
dict
->
cls
,
dict_cls
)
||
dict
->
cls
==
attrwrapper_cls
,
"%s"
,
getTypeName
(
dict
));
ASSERT
(
isSubclass
(
dict
->
cls
,
dict_cls
)
||
dict
->
cls
==
attrwrapper_cls
,
"%s"
,
getTypeName
(
dict
));
if
(
isSubclass
(
dict
->
cls
,
dict_cls
))
{
BoxedDict
*
d
=
static_cast
<
BoxedDict
*>
(
dict
);
auto
it
=
d
->
d
.
find
(
key
);
if
(
it
!=
d
->
d
.
end
())
return
it
->
second
;
return
NULL
;
}
// This path doesn't exist in CPython; we have it to support extension modules that do
// something along the lines of PyDict_GetItem(PyModule_GetDict()):
try
{
try
{
return
getitem
(
dict
,
key
);
return
getitem
(
dict
,
key
);
}
catch
(
ExcInfo
e
)
{
}
catch
(
ExcInfo
e
)
{
...
...
src/runtime/objmodel.cpp
View file @
933834be
...
@@ -318,8 +318,8 @@ void BoxedClass::freeze() {
...
@@ -318,8 +318,8 @@ void BoxedClass::freeze() {
BoxedClass
::
BoxedClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
BoxedClass
::
BoxedClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
)
int
instance_size
,
bool
is_user_defined
)
:
BoxVar
(
0
),
gc_visit
(
gc_visit
),
simple_destructor
(
NULL
),
attrs_offset
(
attrs_offset
),
is_constant
(
false
),
:
BoxVar
(
0
),
attrs
(
HiddenClass
::
makeSingleton
()),
gc_visit
(
gc_visit
),
simple_destructor
(
NULL
),
is_user_defined
(
is_user_defined
),
is_pyston_class
(
true
)
{
attrs_offset
(
attrs_offset
),
is_constant
(
false
),
is_user_defined
(
is_user_defined
),
is_pyston_class
(
true
)
{
// Zero out the CPython tp_* slots:
// Zero out the CPython tp_* slots:
memset
(
&
tp_name
,
0
,
(
char
*
)(
&
tp_version_tag
+
1
)
-
(
char
*
)(
&
tp_name
));
memset
(
&
tp_name
,
0
,
(
char
*
)(
&
tp_version_tag
+
1
)
-
(
char
*
)(
&
tp_name
));
...
@@ -481,6 +481,43 @@ const char* getNameOfClass(BoxedClass* cls) {
...
@@ -481,6 +481,43 @@ const char* getNameOfClass(BoxedClass* cls) {
return
cls
->
tp_name
;
return
cls
->
tp_name
;
}
}
void
HiddenClass
::
appendAttribute
(
llvm
::
StringRef
attr
)
{
assert
(
type
==
SINGLETON
);
dependent_getattrs
.
invalidateAll
();
assert
(
attr_offsets
.
count
(
attr
)
==
0
);
int
n
=
this
->
attributeArraySize
();
attr_offsets
[
attr
]
=
n
;
}
void
HiddenClass
::
appendAttrwrapper
()
{
assert
(
type
==
SINGLETON
);
dependent_getattrs
.
invalidateAll
();
assert
(
attrwrapper_offset
==
-
1
);
attrwrapper_offset
=
this
->
attributeArraySize
();
}
void
HiddenClass
::
delAttribute
(
llvm
::
StringRef
attr
)
{
assert
(
type
==
SINGLETON
);
dependent_getattrs
.
invalidateAll
();
assert
(
attr_offsets
.
count
(
attr
));
int
prev_idx
=
attr_offsets
[
attr
];
attr_offsets
.
erase
(
attr
);
for
(
auto
it
=
attr_offsets
.
begin
(),
end
=
attr_offsets
.
end
();
it
!=
end
;
++
it
)
{
assert
(
it
->
second
!=
prev_idx
);
if
(
it
->
second
>
prev_idx
)
it
->
second
--
;
}
if
(
attrwrapper_offset
!=
-
1
&&
attrwrapper_offset
>
prev_idx
)
attrwrapper_offset
--
;
}
void
HiddenClass
::
addDependence
(
Rewriter
*
rewriter
)
{
assert
(
type
==
SINGLETON
);
rewriter
->
addDependenceOn
(
dependent_getattrs
);
}
HiddenClass
*
HiddenClass
::
getOrMakeChild
(
const
std
::
string
&
attr
)
{
HiddenClass
*
HiddenClass
::
getOrMakeChild
(
const
std
::
string
&
attr
)
{
STAT_TIMER
(
t0
,
"us_timer_hiddenclass_getOrMakeChild"
);
STAT_TIMER
(
t0
,
"us_timer_hiddenclass_getOrMakeChild"
);
assert
(
type
==
NORMAL
);
assert
(
type
==
NORMAL
);
...
@@ -629,14 +666,16 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
...
@@ -629,14 +666,16 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
return
r
;
return
r
;
}
}
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
);
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
);
if
(
rewrite_args
)
rewrite_args
->
out_success
=
true
;
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
if
(
!
rewrite_args
->
obj_hcls_guarded
)
if
(
!
rewrite_args
->
obj_hcls_guarded
)
{
rewrite_args
->
obj
->
addAttrGuard
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
(
intptr_t
)
hcls
);
rewrite_args
->
obj
->
addAttrGuard
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
(
intptr_t
)
hcls
);
if
(
hcls
->
type
==
HiddenClass
::
SINGLETON
)
hcls
->
addDependence
(
rewrite_args
->
rewriter
);
}
rewrite_args
->
out_success
=
true
;
}
}
int
offset
=
hcls
->
getOffset
(
attr
);
int
offset
=
hcls
->
getOffset
(
attr
);
...
@@ -645,8 +684,6 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
...
@@ -645,8 +684,6 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
}
}
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
// TODO using the output register as the temporary makes register allocation easier
// since we don't need to clobber a register, but does it make the code slower?
RewriterVar
*
r_attrs
RewriterVar
*
r_attrs
=
rewrite_args
->
obj
->
getAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
Location
::
any
());
=
rewrite_args
->
obj
->
getAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
Location
::
any
());
rewrite_args
->
out_rtn
=
r_attrs
->
getAttr
(
offset
*
sizeof
(
Box
*
)
+
ATTRLIST_ATTRS_OFFSET
,
Location
::
any
());
rewrite_args
->
out_rtn
=
r_attrs
->
getAttr
(
offset
*
sizeof
(
Box
*
)
+
ATTRLIST_ATTRS_OFFSET
,
Location
::
any
());
...
@@ -676,20 +713,12 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
...
@@ -676,20 +713,12 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
return
NULL
;
return
NULL
;
}
}
void
Box
::
a
ddNewHCAttr
(
HiddenClass
*
new_hcls
,
Box
*
new_attr
,
SetattrRewriteArgs
*
rewrite_args
)
{
void
Box
::
a
ppendNewHCAttr
(
Box
*
new_attr
,
SetattrRewriteArgs
*
rewrite_args
)
{
assert
(
cls
->
instancesHaveHCAttrs
());
assert
(
cls
->
instancesHaveHCAttrs
());
HCAttrs
*
attrs
=
getHCAttrsPtr
();
HCAttrs
*
attrs
=
getHCAttrsPtr
();
HiddenClass
*
hcls
=
attrs
->
hcls
;
HiddenClass
*
hcls
=
attrs
->
hcls
;
#ifndef NDEBUG
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
);
// make sure we don't need to rearrange the attributes
assert
(
new_hcls
->
attributeArraySize
()
==
hcls
->
attributeArraySize
()
+
1
);
for
(
const
auto
&
p
:
hcls
->
getStrAttrOffsets
())
{
assert
(
new_hcls
->
getStrAttrOffsets
().
lookup
(
p
.
first
())
==
p
.
second
);
}
if
(
hcls
->
getAttrwrapperOffset
()
!=
-
1
)
assert
(
hcls
->
getAttrwrapperOffset
()
==
new_hcls
->
getAttrwrapperOffset
());
#endif
int
numattrs
=
hcls
->
attributeArraySize
();
int
numattrs
=
hcls
->
attributeArraySize
();
...
@@ -711,18 +740,11 @@ void Box::addNewHCAttr(HiddenClass* new_hcls, Box* new_attr, SetattrRewriteArgs*
...
@@ -711,18 +740,11 @@ void Box::addNewHCAttr(HiddenClass* new_hcls, Box* new_attr, SetattrRewriteArgs*
r_new_array2
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
gc
::
gc_realloc
,
r_oldarray
,
r_newsize
);
r_new_array2
=
rewrite_args
->
rewriter
->
call
(
true
,
(
void
*
)
gc
::
gc_realloc
,
r_oldarray
,
r_newsize
);
}
}
}
}
// Don't set the new hcls until after we do the allocation for the new attr_list;
// that allocation can cause a collection, and we want the collector to always
// see a consistent state between the hcls and the attr_list
attrs
->
hcls
=
new_hcls
;
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
r_new_array2
->
setAttr
(
numattrs
*
sizeof
(
Box
*
)
+
ATTRLIST_ATTRS_OFFSET
,
rewrite_args
->
attrval
);
r_new_array2
->
setAttr
(
numattrs
*
sizeof
(
Box
*
)
+
ATTRLIST_ATTRS_OFFSET
,
rewrite_args
->
attrval
);
rewrite_args
->
obj
->
setAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
r_new_array2
);
rewrite_args
->
obj
->
setAttr
(
cls
->
attrs_offset
+
HCATTRS_ATTRS_OFFSET
,
r_new_array2
);
RewriterVar
*
r_hcls
=
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
new_hcls
);
rewrite_args
->
obj
->
setAttr
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
r_hcls
);
rewrite_args
->
out_success
=
true
;
rewrite_args
->
out_success
=
true
;
}
}
attrs
->
attr_list
->
attrs
[
numattrs
]
=
new_attr
;
attrs
->
attr_list
->
attrs
[
numattrs
]
=
new_attr
;
...
@@ -760,13 +782,14 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
...
@@ -760,13 +782,14 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
return
;
return
;
}
}
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
);
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
);
int
offset
=
hcls
->
getOffset
(
attr
);
int
offset
=
hcls
->
getOffset
(
attr
);
if
(
rewrite_args
)
{
if
(
rewrite_args
)
{
rewrite_args
->
obj
->
addAttrGuard
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
(
intptr_t
)
hcls
);
rewrite_args
->
obj
->
addAttrGuard
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
(
intptr_t
)
hcls
);
// rewrite_args->rewriter->addDecision(offset == -1 ? 1 : 0);
if
(
hcls
->
type
==
HiddenClass
::
SINGLETON
)
hcls
->
addDependence
(
rewrite_args
->
rewriter
);
}
}
if
(
offset
>=
0
)
{
if
(
offset
>=
0
)
{
...
@@ -788,12 +811,33 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
...
@@ -788,12 +811,33 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
}
}
assert
(
offset
==
-
1
);
assert
(
offset
==
-
1
);
HiddenClass
*
new_hcls
=
hcls
->
getOrMakeChild
(
attr
);
// make sure we don't need to rearrange the attributes
if
(
hcls
->
type
==
HiddenClass
::
NORMAL
)
{
assert
(
new_hcls
->
getStrAttrOffsets
().
lookup
(
attr
)
==
hcls
->
attributeArraySize
());
HiddenClass
*
new_hcls
=
hcls
->
getOrMakeChild
(
attr
);
// make sure we don't need to rearrange the attributes
assert
(
new_hcls
->
getStrAttrOffsets
().
lookup
(
attr
)
==
hcls
->
attributeArraySize
());
addNewHCAttr
(
new_hcls
,
val
,
rewrite_args
);
this
->
appendNewHCAttr
(
val
,
rewrite_args
);
attrs
->
hcls
=
new_hcls
;
if
(
rewrite_args
)
{
if
(
!
rewrite_args
->
out_success
)
{
rewrite_args
=
NULL
;
}
else
{
RewriterVar
*
r_hcls
=
rewrite_args
->
rewriter
->
loadConst
((
intptr_t
)
new_hcls
);
rewrite_args
->
obj
->
setAttr
(
cls
->
attrs_offset
+
HCATTRS_HCLS_OFFSET
,
r_hcls
);
rewrite_args
->
out_success
=
true
;
}
}
}
else
{
assert
(
hcls
->
type
==
HiddenClass
::
SINGLETON
);
assert
(
!
rewrite_args
||
!
rewrite_args
->
out_success
);
rewrite_args
=
NULL
;
this
->
appendNewHCAttr
(
val
,
NULL
);
hcls
->
appendAttribute
(
attr
);
}
return
;
return
;
}
}
...
@@ -3825,8 +3869,7 @@ void Box::delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args) {
...
@@ -3825,8 +3869,7 @@ void Box::delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args) {
return
;
return
;
}
}
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
);
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
);
HiddenClass
*
new_hcls
=
hcls
->
delAttrToMakeHC
(
attr
);
// The order of attributes is pertained as delAttrToMakeHC constructs
// The order of attributes is pertained as delAttrToMakeHC constructs
// the new HiddenClass by invoking getOrMakeChild in the prevous order
// the new HiddenClass by invoking getOrMakeChild in the prevous order
...
@@ -3837,7 +3880,13 @@ void Box::delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args) {
...
@@ -3837,7 +3880,13 @@ void Box::delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args) {
Box
**
start
=
attrs
->
attr_list
->
attrs
;
Box
**
start
=
attrs
->
attr_list
->
attrs
;
memmove
(
start
+
offset
,
start
+
offset
+
1
,
(
num_attrs
-
offset
-
1
)
*
sizeof
(
Box
*
));
memmove
(
start
+
offset
,
start
+
offset
+
1
,
(
num_attrs
-
offset
-
1
)
*
sizeof
(
Box
*
));
attrs
->
hcls
=
new_hcls
;
if
(
hcls
->
type
==
HiddenClass
::
NORMAL
)
{
HiddenClass
*
new_hcls
=
hcls
->
delAttrToMakeHC
(
attr
);
attrs
->
hcls
=
new_hcls
;
}
else
{
assert
(
hcls
->
type
==
HiddenClass
::
SINGLETON
);
hcls
->
delAttribute
(
attr
);
}
// guarantee the size of the attr_list equals the number of attrs
// guarantee the size of the attr_list equals the number of attrs
int
new_size
=
sizeof
(
HCAttrs
::
AttrList
)
+
sizeof
(
Box
*
)
*
(
num_attrs
-
1
);
int
new_size
=
sizeof
(
HCAttrs
::
AttrList
)
+
sizeof
(
Box
*
)
*
(
num_attrs
-
1
);
...
...
src/runtime/types.cpp
View file @
933834be
...
@@ -383,7 +383,8 @@ static void functionDtor(Box* b) {
...
@@ -383,7 +383,8 @@ static void functionDtor(Box* b) {
}
}
// TODO(kmod): builtin modules are not supposed to have a __file__ attribute
// TODO(kmod): builtin modules are not supposed to have a __file__ attribute
BoxedModule
::
BoxedModule
(
const
std
::
string
&
name
,
const
std
::
string
&
fn
,
const
char
*
doc
)
{
BoxedModule
::
BoxedModule
(
const
std
::
string
&
name
,
const
std
::
string
&
fn
,
const
char
*
doc
)
:
attrs
(
HiddenClass
::
makeSingleton
())
{
this
->
giveAttr
(
"__name__"
,
boxString
(
name
));
this
->
giveAttr
(
"__name__"
,
boxString
(
name
));
this
->
giveAttr
(
"__file__"
,
boxString
(
fn
));
this
->
giveAttr
(
"__file__"
,
boxString
(
fn
));
this
->
giveAttr
(
"__doc__"
,
doc
?
boxStrConstant
(
doc
)
:
None
);
this
->
giveAttr
(
"__doc__"
,
doc
?
boxStrConstant
(
doc
)
:
None
);
...
@@ -1255,7 +1256,8 @@ public:
...
@@ -1255,7 +1256,8 @@ public:
// This check doesn't cover all cases, since an attrwrapper could be created around
// This check doesn't cover all cases, since an attrwrapper could be created around
// a normal object which then becomes dict-backed, so we RELEASE_ASSERT later
// a normal object which then becomes dict-backed, so we RELEASE_ASSERT later
// that that doesn't happen.
// that that doesn't happen.
assert
(
b
->
getHCAttrsPtr
()
->
hcls
->
type
==
HiddenClass
::
NORMAL
);
assert
(
b
->
getHCAttrsPtr
()
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
b
->
getHCAttrsPtr
()
->
hcls
->
type
==
HiddenClass
::
SINGLETON
);
}
}
DEFAULT_CLASS
(
attrwrapper_cls
);
DEFAULT_CLASS
(
attrwrapper_cls
);
...
@@ -1374,7 +1376,7 @@ public:
...
@@ -1374,7 +1376,7 @@ public:
os
<<
"attrwrapper({"
;
os
<<
"attrwrapper({"
;
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
attrs
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
bool
first
=
true
;
bool
first
=
true
;
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
if
(
!
first
)
if
(
!
first
)
...
@@ -1407,7 +1409,7 @@ public:
...
@@ -1407,7 +1409,7 @@ public:
BoxedList
*
rtn
=
new
BoxedList
();
BoxedList
*
rtn
=
new
BoxedList
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
attrs
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
listAppend
(
rtn
,
boxString
(
p
.
first
()));
listAppend
(
rtn
,
boxString
(
p
.
first
()));
}
}
...
@@ -1422,7 +1424,7 @@ public:
...
@@ -1422,7 +1424,7 @@ public:
BoxedList
*
rtn
=
new
BoxedList
();
BoxedList
*
rtn
=
new
BoxedList
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
attrs
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
listAppend
(
rtn
,
attrs
->
attr_list
->
attrs
[
p
.
second
]);
listAppend
(
rtn
,
attrs
->
attr_list
->
attrs
[
p
.
second
]);
}
}
...
@@ -1437,7 +1439,7 @@ public:
...
@@ -1437,7 +1439,7 @@ public:
BoxedList
*
rtn
=
new
BoxedList
();
BoxedList
*
rtn
=
new
BoxedList
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
attrs
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
BoxedTuple
*
t
=
BoxedTuple
::
create
({
boxString
(
p
.
first
()),
attrs
->
attr_list
->
attrs
[
p
.
second
]
});
BoxedTuple
*
t
=
BoxedTuple
::
create
({
boxString
(
p
.
first
()),
attrs
->
attr_list
->
attrs
[
p
.
second
]
});
listAppend
(
rtn
,
t
);
listAppend
(
rtn
,
t
);
...
@@ -1452,7 +1454,7 @@ public:
...
@@ -1452,7 +1454,7 @@ public:
BoxedDict
*
rtn
=
new
BoxedDict
();
BoxedDict
*
rtn
=
new
BoxedDict
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
attrs
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
rtn
->
d
[
boxString
(
p
.
first
())]
=
attrs
->
attr_list
->
attrs
[
p
.
second
];
rtn
->
d
[
boxString
(
p
.
first
())]
=
attrs
->
attr_list
->
attrs
[
p
.
second
];
}
}
...
@@ -1464,7 +1466,7 @@ public:
...
@@ -1464,7 +1466,7 @@ public:
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
HCAttrs
*
attrs
=
self
->
b
->
getHCAttrsPtr
();
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
attrs
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
return
boxInt
(
attrs
->
hcls
->
getStrAttrOffsets
().
size
());
return
boxInt
(
attrs
->
hcls
->
getStrAttrOffsets
().
size
());
}
}
...
@@ -1477,7 +1479,7 @@ public:
...
@@ -1477,7 +1479,7 @@ public:
AttrWrapper
*
container
=
static_cast
<
AttrWrapper
*>
(
_container
);
AttrWrapper
*
container
=
static_cast
<
AttrWrapper
*>
(
_container
);
HCAttrs
*
attrs
=
container
->
b
->
getHCAttrsPtr
();
HCAttrs
*
attrs
=
container
->
b
->
getHCAttrsPtr
();
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
attrs
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
attrs
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
self
->
b
->
setattr
(
p
.
first
(),
attrs
->
attr_list
->
attrs
[
p
.
second
],
NULL
);
self
->
b
->
setattr
(
p
.
first
(),
attrs
->
attr_list
->
attrs
[
p
.
second
],
NULL
);
}
}
...
@@ -1506,14 +1508,14 @@ public:
...
@@ -1506,14 +1508,14 @@ public:
AttrWrapperIter
::
AttrWrapperIter
(
AttrWrapper
*
aw
)
{
AttrWrapperIter
::
AttrWrapperIter
(
AttrWrapper
*
aw
)
{
hcls
=
aw
->
b
->
getHCAttrsPtr
()
->
hcls
;
hcls
=
aw
->
b
->
getHCAttrsPtr
()
->
hcls
;
assert
(
hcls
);
assert
(
hcls
);
RELEASE_ASSERT
(
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
it
=
hcls
->
getStrAttrOffsets
().
begin
();
it
=
hcls
->
getStrAttrOffsets
().
begin
();
}
}
Box
*
AttrWrapperIter
::
hasnext
(
Box
*
_self
)
{
Box
*
AttrWrapperIter
::
hasnext
(
Box
*
_self
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapperiter_cls
,
""
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapperiter_cls
,
""
);
AttrWrapperIter
*
self
=
static_cast
<
AttrWrapperIter
*>
(
_self
);
AttrWrapperIter
*
self
=
static_cast
<
AttrWrapperIter
*>
(
_self
);
RELEASE_ASSERT
(
self
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
self
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
self
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
return
boxBool
(
self
->
it
!=
self
->
hcls
->
getStrAttrOffsets
().
end
());
return
boxBool
(
self
->
it
!=
self
->
hcls
->
getStrAttrOffsets
().
end
());
}
}
...
@@ -1521,7 +1523,7 @@ Box* AttrWrapperIter::hasnext(Box* _self) {
...
@@ -1521,7 +1523,7 @@ Box* AttrWrapperIter::hasnext(Box* _self) {
Box
*
AttrWrapperIter
::
next
(
Box
*
_self
)
{
Box
*
AttrWrapperIter
::
next
(
Box
*
_self
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapperiter_cls
,
""
);
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapperiter_cls
,
""
);
AttrWrapperIter
*
self
=
static_cast
<
AttrWrapperIter
*>
(
_self
);
AttrWrapperIter
*
self
=
static_cast
<
AttrWrapperIter
*>
(
_self
);
RELEASE_ASSERT
(
self
->
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
self
->
hcls
->
type
==
HiddenClass
::
NORMAL
||
self
->
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
assert
(
self
->
it
!=
self
->
hcls
->
getStrAttrOffsets
().
end
());
assert
(
self
->
it
!=
self
->
hcls
->
getStrAttrOffsets
().
end
());
Box
*
r
=
boxString
(
self
->
it
->
first
());
Box
*
r
=
boxString
(
self
->
it
->
first
());
...
@@ -1541,8 +1543,17 @@ Box* Box::getAttrWrapper() {
...
@@ -1541,8 +1543,17 @@ Box* Box::getAttrWrapper() {
int
offset
=
hcls
->
getAttrwrapperOffset
();
int
offset
=
hcls
->
getAttrwrapperOffset
();
if
(
offset
==
-
1
)
{
if
(
offset
==
-
1
)
{
Box
*
aw
=
new
AttrWrapper
(
this
);
Box
*
aw
=
new
AttrWrapper
(
this
);
addNewHCAttr
(
hcls
->
getAttrwrapperChild
(),
aw
,
NULL
);
if
(
hcls
->
type
==
HiddenClass
::
NORMAL
)
{
return
aw
;
auto
new_hcls
=
hcls
->
getAttrwrapperChild
();
appendNewHCAttr
(
aw
,
NULL
);
attrs
->
hcls
=
new_hcls
;
return
aw
;
}
else
{
assert
(
hcls
->
type
==
HiddenClass
::
SINGLETON
);
appendNewHCAttr
(
aw
,
NULL
);
hcls
->
appendAttrwrapper
();
return
aw
;
}
}
}
return
attrs
->
attr_list
->
attrs
[
offset
];
return
attrs
->
attr_list
->
attrs
[
offset
];
}
}
...
...
src/runtime/types.h
View file @
933834be
...
@@ -278,6 +278,7 @@ public:
...
@@ -278,6 +278,7 @@ public:
enum
HCType
{
enum
HCType
{
NORMAL
,
// attributes stored in attributes array, name->offset map stored in hidden class
NORMAL
,
// attributes stored in attributes array, name->offset map stored in hidden class
DICT_BACKED
,
// first attribute in array is a dict-like object which stores the attributes
DICT_BACKED
,
// first attribute in array is a dict-like object which stores the attributes
SINGLETON
,
// name->offset map stored in hidden class, but hcls is mutable
}
const
type
;
}
const
type
;
static
HiddenClass
*
dict_backed
;
static
HiddenClass
*
dict_backed
;
...
@@ -291,14 +292,21 @@ private:
...
@@ -291,14 +292,21 @@ private:
}
}
}
}
// These fields only make sense for NORMAL hidden classes:
// These fields only make sense for NORMAL
or SINGLETON
hidden classes:
llvm
::
StringMap
<
int
>
attr_offsets
;
llvm
::
StringMap
<
int
>
attr_offsets
;
ContiguousMap
<
llvm
::
StringRef
,
HiddenClass
*
,
llvm
::
StringMap
<
int
>>
children
;
// If >= 0, is the offset where we stored an attrwrapper object
// If >= 0, is the offset where we stored an attrwrapper object
int
attrwrapper_offset
=
-
1
;
int
attrwrapper_offset
=
-
1
;
// These are only for NORMAL hidden classes:
ContiguousMap
<
llvm
::
StringRef
,
HiddenClass
*
,
llvm
::
StringMap
<
int
>>
children
;
HiddenClass
*
attrwrapper_child
=
NULL
;
HiddenClass
*
attrwrapper_child
=
NULL
;
// Only for SINGLETON hidden classes:
ICInvalidator
dependent_getattrs
;
public:
public:
static
HiddenClass
*
makeSingleton
()
{
return
new
HiddenClass
(
SINGLETON
);
}
static
HiddenClass
*
makeRoot
()
{
static
HiddenClass
*
makeRoot
()
{
#ifndef NDEBUG
#ifndef NDEBUG
static
bool
made
=
false
;
static
bool
made
=
false
;
...
@@ -329,7 +337,7 @@ public:
...
@@ -329,7 +337,7 @@ public:
if
(
type
==
DICT_BACKED
)
if
(
type
==
DICT_BACKED
)
return
1
;
return
1
;
ASSERT
(
type
==
NORMAL
,
"%d"
,
type
);
ASSERT
(
type
==
NORMAL
||
type
==
SINGLETON
,
"%d"
,
type
);
int
r
=
attr_offsets
.
size
();
int
r
=
attr_offsets
.
size
();
if
(
attrwrapper_offset
!=
-
1
)
if
(
attrwrapper_offset
!=
-
1
)
r
+=
1
;
r
+=
1
;
...
@@ -338,18 +346,18 @@ public:
...
@@ -338,18 +346,18 @@ public:
// The mapping from string attribute names to attribute offsets. There may be other objects in the attributes
// The mapping from string attribute names to attribute offsets. There may be other objects in the attributes
// array.
// array.
// Only valid for NORMAL hidden classes
// Only valid for NORMAL
or SINGLETON
hidden classes
const
llvm
::
StringMap
<
int
>&
getStrAttrOffsets
()
{
const
llvm
::
StringMap
<
int
>&
getStrAttrOffsets
()
{
assert
(
type
==
NORMAL
);
assert
(
type
==
NORMAL
||
type
==
SINGLETON
);
return
attr_offsets
;
return
attr_offsets
;
}
}
// Only valid for NORMAL hidden classes:
// Only valid for NORMAL hidden classes:
HiddenClass
*
getOrMakeChild
(
const
std
::
string
&
attr
);
HiddenClass
*
getOrMakeChild
(
const
std
::
string
&
attr
);
// Only valid for NORMAL hidden classes:
// Only valid for NORMAL
or SINGLETON
hidden classes:
int
getOffset
(
const
std
::
string
&
attr
)
{
int
getOffset
(
const
std
::
string
&
attr
)
{
assert
(
type
==
NORMAL
);
assert
(
type
==
NORMAL
||
type
==
SINGLETON
);
auto
it
=
attr_offsets
.
find
(
attr
);
auto
it
=
attr_offsets
.
find
(
attr
);
if
(
it
==
attr_offsets
.
end
())
if
(
it
==
attr_offsets
.
end
())
return
-
1
;
return
-
1
;
...
@@ -357,10 +365,17 @@ public:
...
@@ -357,10 +365,17 @@ public:
}
}
int
getAttrwrapperOffset
()
{
int
getAttrwrapperOffset
()
{
assert
(
type
==
NORMAL
);
assert
(
type
==
NORMAL
||
type
==
SINGLETON
);
return
attrwrapper_offset
;
return
attrwrapper_offset
;
}
}
// Only valid for SINGLETON hidden classes:
void
appendAttribute
(
llvm
::
StringRef
attr
);
void
appendAttrwrapper
();
void
delAttribute
(
llvm
::
StringRef
attr
);
void
addDependence
(
Rewriter
*
rewriter
);
// Only valid for NORMAL hidden classes:
HiddenClass
*
getAttrwrapperChild
();
HiddenClass
*
getAttrwrapperChild
();
// Only valid for NORMAL hidden classes:
// Only valid for NORMAL hidden classes:
...
...
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