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 {
RELEASE_ASSERT
(
cls
->
tp_del
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_version_tag
==
0
,
""
);
// I think it is safe to ignore these for for now:
// RELEASE_ASSERT(cls->tp_weaklistoffset == 0, "");
// RELEASE_ASSERT(cls->tp_traverse == NULL, "");
// RELEASE_ASSERT(cls->tp_clear == NULL, "");
// I think it is safe to ignore these for for now:
// RELEASE_ASSERT(cls->tp_weaklistoffset == 0, "");
// RELEASE_ASSERT(cls->tp_traverse == 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)
INITIALIZE
(
cls
->
attrs
);
INITIALIZE
(
cls
->
dependent_icgetattrs
);
#undef INITIALIZE
...
...
src/core/types.h
View file @
933834be
...
...
@@ -418,7 +418,7 @@ public:
HiddenClass
*
hcls
;
AttrList
*
attr_list
;
HCAttrs
(
)
:
hcls
(
root_
hcls
),
attr_list
(
nullptr
)
{}
HCAttrs
(
HiddenClass
*
hcls
=
root_hcls
)
:
hcls
(
hcls
),
attr_list
(
nullptr
)
{}
};
class
BoxedDict
;
...
...
@@ -428,11 +428,8 @@ class Box {
private:
BoxedDict
**
getDictPtr
();
// Adds a new attribute to a HCAttrs-backed object. Must pass in the new hidden class object
// which must be the same as the current hidden class but with the new attribute at the end.
// 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
);
// Appends a new value to the hcattrs array.
void
appendNewHCAttr
(
Box
*
val
,
SetattrRewriteArgs
*
rewrite_args
);
public:
// 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 {
TypeStats
total
;
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
));
}
};
...
...
@@ -233,6 +233,10 @@ void addStatistic(HeapStatistics* stats, GCAllocation* al, int nbytes) {
Box
*
b
=
(
Box
*
)
al
->
user_data
;
if
(
b
->
cls
->
instancesHaveHCAttrs
())
{
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
]
++
;
}
}
...
...
src/runtime/dict.cpp
View file @
933834be
...
...
@@ -228,7 +228,6 @@ extern "C" int PyDict_SetItem(PyObject* mp, PyObject* _key, PyObject* _item) noe
Box
*
item
=
static_cast
<
Box
*>
(
_item
);
try
{
// TODO should demote GIL?
setitem
(
b
,
key
,
item
);
}
catch
(
ExcInfo
e
)
{
abort
();
...
...
@@ -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
{
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
{
return
getitem
(
dict
,
key
);
}
catch
(
ExcInfo
e
)
{
...
...
src/runtime/objmodel.cpp
View file @
933834be
...
...
@@ -318,8 +318,8 @@ void BoxedClass::freeze() {
BoxedClass
::
BoxedClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
)
:
BoxVar
(
0
),
gc_visit
(
gc_visit
),
simple_destructor
(
NULL
),
attrs_offset
(
attrs_offset
),
is_constant
(
false
),
is_user_defined
(
is_user_defined
),
is_pyston_class
(
true
)
{
:
BoxVar
(
0
),
attrs
(
HiddenClass
::
makeSingleton
()),
gc_visit
(
gc_visit
),
simple_destructor
(
NULL
),
attrs_offset
(
attrs_offset
),
is_constant
(
false
),
is_user_defined
(
is_user_defined
),
is_pyston_class
(
true
)
{
// Zero out the CPython tp_* slots:
memset
(
&
tp_name
,
0
,
(
char
*
)(
&
tp_version_tag
+
1
)
-
(
char
*
)(
&
tp_name
));
...
...
@@ -481,6 +481,43 @@ const char* getNameOfClass(BoxedClass* cls) {
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
)
{
STAT_TIMER
(
t0
,
"us_timer_hiddenclass_getOrMakeChild"
);
assert
(
type
==
NORMAL
);
...
...
@@ -629,14 +666,16 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
return
r
;
}
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
);
if
(
rewrite_args
)
rewrite_args
->
out_success
=
true
;
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
);
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
);
if
(
hcls
->
type
==
HiddenClass
::
SINGLETON
)
hcls
->
addDependence
(
rewrite_args
->
rewriter
);
}
rewrite_args
->
out_success
=
true
;
}
int
offset
=
hcls
->
getOffset
(
attr
);
...
...
@@ -645,8 +684,6 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* 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
=
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
());
...
...
@@ -676,20 +713,12 @@ Box* Box::getattr(const std::string& attr, GetattrRewriteArgs* rewrite_args) {
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
());
HCAttrs
*
attrs
=
getHCAttrsPtr
();
HiddenClass
*
hcls
=
attrs
->
hcls
;
#ifndef NDEBUG
// 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
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
);
int
numattrs
=
hcls
->
attributeArraySize
();
...
...
@@ -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
);
}
}
// 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
)
{
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
);
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
;
}
attrs
->
attr_list
->
attrs
[
numattrs
]
=
new_attr
;
...
...
@@ -760,13 +782,14 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
return
;
}
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
);
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
);
int
offset
=
hcls
->
getOffset
(
attr
);
if
(
rewrite_args
)
{
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
)
{
...
...
@@ -788,12 +811,33 @@ void Box::setattr(const std::string& attr, Box* val, SetattrRewriteArgs* rewrite
}
assert
(
offset
==
-
1
);
HiddenClass
*
new_hcls
=
hcls
->
getOrMakeChild
(
attr
);
// make sure we don't need to rearrange the attributes
assert
(
new_hcls
->
getStrAttrOffsets
().
lookup
(
attr
)
==
hcls
->
attributeArraySize
());
if
(
hcls
->
type
==
HiddenClass
::
NORMAL
)
{
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
;
}
...
...
@@ -3825,8 +3869,7 @@ void Box::delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args) {
return
;
}
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
);
HiddenClass
*
new_hcls
=
hcls
->
delAttrToMakeHC
(
attr
);
assert
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
);
// The order of attributes is pertained as delAttrToMakeHC constructs
// the new HiddenClass by invoking getOrMakeChild in the prevous order
...
...
@@ -3837,7 +3880,13 @@ void Box::delattr(const std::string& attr, DelattrRewriteArgs* rewrite_args) {
Box
**
start
=
attrs
->
attr_list
->
attrs
;
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
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) {
}
// 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
(
"__file__"
,
boxString
(
fn
));
this
->
giveAttr
(
"__doc__"
,
doc
?
boxStrConstant
(
doc
)
:
None
);
...
...
@@ -1255,7 +1256,8 @@ public:
// 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
// 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
);
...
...
@@ -1374,7 +1376,7 @@ public:
os
<<
"attrwrapper({"
;
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
;
for
(
const
auto
&
p
:
attrs
->
hcls
->
getStrAttrOffsets
())
{
if
(
!
first
)
...
...
@@ -1407,7 +1409,7 @@ public:
BoxedList
*
rtn
=
new
BoxedList
();
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
())
{
listAppend
(
rtn
,
boxString
(
p
.
first
()));
}
...
...
@@ -1422,7 +1424,7 @@ public:
BoxedList
*
rtn
=
new
BoxedList
();
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
())
{
listAppend
(
rtn
,
attrs
->
attr_list
->
attrs
[
p
.
second
]);
}
...
...
@@ -1437,7 +1439,7 @@ public:
BoxedList
*
rtn
=
new
BoxedList
();
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
())
{
BoxedTuple
*
t
=
BoxedTuple
::
create
({
boxString
(
p
.
first
()),
attrs
->
attr_list
->
attrs
[
p
.
second
]
});
listAppend
(
rtn
,
t
);
...
...
@@ -1452,7 +1454,7 @@ public:
BoxedDict
*
rtn
=
new
BoxedDict
();
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
())
{
rtn
->
d
[
boxString
(
p
.
first
())]
=
attrs
->
attr_list
->
attrs
[
p
.
second
];
}
...
...
@@ -1464,7 +1466,7 @@ public:
AttrWrapper
*
self
=
static_cast
<
AttrWrapper
*>
(
_self
);
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
());
}
...
...
@@ -1477,7 +1479,7 @@ public:
AttrWrapper
*
container
=
static_cast
<
AttrWrapper
*>
(
_container
);
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
())
{
self
->
b
->
setattr
(
p
.
first
(),
attrs
->
attr_list
->
attrs
[
p
.
second
],
NULL
);
}
...
...
@@ -1506,14 +1508,14 @@ public:
AttrWrapperIter
::
AttrWrapperIter
(
AttrWrapper
*
aw
)
{
hcls
=
aw
->
b
->
getHCAttrsPtr
()
->
hcls
;
assert
(
hcls
);
RELEASE_ASSERT
(
hcls
->
type
==
HiddenClass
::
NORMAL
,
""
);
RELEASE_ASSERT
(
hcls
->
type
==
HiddenClass
::
NORMAL
||
hcls
->
type
==
HiddenClass
::
SINGLETON
,
""
);
it
=
hcls
->
getStrAttrOffsets
().
begin
();
}
Box
*
AttrWrapperIter
::
hasnext
(
Box
*
_self
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapperiter_cls
,
""
);
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
());
}
...
...
@@ -1521,7 +1523,7 @@ Box* AttrWrapperIter::hasnext(Box* _self) {
Box
*
AttrWrapperIter
::
next
(
Box
*
_self
)
{
RELEASE_ASSERT
(
_self
->
cls
==
attrwrapperiter_cls
,
""
);
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
());
Box
*
r
=
boxString
(
self
->
it
->
first
());
...
...
@@ -1541,8 +1543,17 @@ Box* Box::getAttrWrapper() {
int
offset
=
hcls
->
getAttrwrapperOffset
();
if
(
offset
==
-
1
)
{
Box
*
aw
=
new
AttrWrapper
(
this
);
addNewHCAttr
(
hcls
->
getAttrwrapperChild
(),
aw
,
NULL
);
return
aw
;
if
(
hcls
->
type
==
HiddenClass
::
NORMAL
)
{
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
];
}
...
...
src/runtime/types.h
View file @
933834be
...
...
@@ -278,6 +278,7 @@ public:
enum
HCType
{
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
SINGLETON
,
// name->offset map stored in hidden class, but hcls is mutable
}
const
type
;
static
HiddenClass
*
dict_backed
;
...
...
@@ -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
;
ContiguousMap
<
llvm
::
StringRef
,
HiddenClass
*
,
llvm
::
StringMap
<
int
>>
children
;
// If >= 0, is the offset where we stored an attrwrapper object
int
attrwrapper_offset
=
-
1
;
// These are only for NORMAL hidden classes:
ContiguousMap
<
llvm
::
StringRef
,
HiddenClass
*
,
llvm
::
StringMap
<
int
>>
children
;
HiddenClass
*
attrwrapper_child
=
NULL
;
// Only for SINGLETON hidden classes:
ICInvalidator
dependent_getattrs
;
public:
static
HiddenClass
*
makeSingleton
()
{
return
new
HiddenClass
(
SINGLETON
);
}
static
HiddenClass
*
makeRoot
()
{
#ifndef NDEBUG
static
bool
made
=
false
;
...
...
@@ -329,7 +337,7 @@ public:
if
(
type
==
DICT_BACKED
)
return
1
;
ASSERT
(
type
==
NORMAL
,
"%d"
,
type
);
ASSERT
(
type
==
NORMAL
||
type
==
SINGLETON
,
"%d"
,
type
);
int
r
=
attr_offsets
.
size
();
if
(
attrwrapper_offset
!=
-
1
)
r
+=
1
;
...
...
@@ -338,18 +346,18 @@ public:
// The mapping from string attribute names to attribute offsets. There may be other objects in the attributes
// array.
// Only valid for NORMAL hidden classes
// Only valid for NORMAL
or SINGLETON
hidden classes
const
llvm
::
StringMap
<
int
>&
getStrAttrOffsets
()
{
assert
(
type
==
NORMAL
);
assert
(
type
==
NORMAL
||
type
==
SINGLETON
);
return
attr_offsets
;
}
// Only valid for NORMAL hidden classes:
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
)
{
assert
(
type
==
NORMAL
);
assert
(
type
==
NORMAL
||
type
==
SINGLETON
);
auto
it
=
attr_offsets
.
find
(
attr
);
if
(
it
==
attr_offsets
.
end
())
return
-
1
;
...
...
@@ -357,10 +365,17 @@ public:
}
int
getAttrwrapperOffset
()
{
assert
(
type
==
NORMAL
);
assert
(
type
==
NORMAL
||
type
==
SINGLETON
);
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
();
// 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