Commit 3843b3d7 authored by Rudi Chen's avatar Rudi Chen

Move hidden class code into a separate file.

Since it's one class and it's big enough, might as well have it's own
file.
parent de52ad0f
......@@ -94,6 +94,7 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
runtime/float.cpp
runtime/frame.cpp
runtime/generator.cpp
runtime/hiddenclass.cpp
runtime/ics.cpp
runtime/import.cpp
runtime/int.cpp
......
......@@ -17,6 +17,7 @@
#include "capi/types.h"
#include "runtime/classobj.h"
#include "runtime/hiddenclass.h"
#include "runtime/objmodel.h"
#include "runtime/rewrite_args.h"
......
......@@ -25,6 +25,7 @@
#include "core/types.h"
#include "core/util.h"
#include "gc/heap.h"
#include "runtime/hiddenclass.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
......@@ -21,6 +21,7 @@
#include "core/common.h"
#include "core/util.h"
#include "gc/gc_alloc.h"
#include "runtime/hiddenclass.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// limitations under the License.
#include "runtime/hiddenclass.h"
#include <cassert>
#include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h"
#include "core/stats.h"
#include "core/types.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"
namespace pyston {
void HiddenClass::appendAttribute(BoxedString* attr) {
assert(attr->interned_state != SSTATE_NOT_INTERNED);
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(BoxedString* attr) {
assert(attr->interned_state != SSTATE_NOT_INTERNED);
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(BoxedString* attr) {
STAT_TIMER(t0, "us_timer_hiddenclass_getOrMakeChild", 0);
assert(attr->interned_state != SSTATE_NOT_INTERNED);
assert(type == NORMAL);
auto it = children.find(attr);
if (it != children.end())
return children.getMapped(it->second);
static StatCounter num_hclses("num_hidden_classes");
num_hclses.log();
HiddenClass* rtn = new HiddenClass(this);
rtn->attr_offsets[attr] = this->attributeArraySize();
this->children[attr] = rtn;
assert(rtn->attributeArraySize() == this->attributeArraySize() + 1);
return rtn;
}
HiddenClass* HiddenClass::getAttrwrapperChild() {
assert(type == NORMAL);
assert(attrwrapper_offset == -1);
if (!attrwrapper_child) {
HiddenClass* made = new HiddenClass(this);
made->attrwrapper_offset = this->attributeArraySize();
this->attrwrapper_child = made;
assert(made->attributeArraySize() == this->attributeArraySize() + 1);
}
return attrwrapper_child;
}
/**
* del attr from current HiddenClass, maintaining the order of the remaining attrs
*/
HiddenClass* HiddenClass::delAttrToMakeHC(BoxedString* attr) {
STAT_TIMER(t0, "us_timer_hiddenclass_delAttrToMakeHC", 0);
assert(attr->interned_state != SSTATE_NOT_INTERNED);
assert(type == NORMAL);
int idx = getOffset(attr);
assert(idx >= 0);
std::vector<BoxedString*> new_attrs(attributeArraySize() - 1);
for (auto it = attr_offsets.begin(); it != attr_offsets.end(); ++it) {
if (it->second < idx)
new_attrs[it->second] = it->first;
else if (it->second > idx) {
new_attrs[it->second - 1] = it->first;
}
}
int new_attrwrapper_offset = attrwrapper_offset;
if (new_attrwrapper_offset > idx)
new_attrwrapper_offset--;
// TODO we can first locate the parent HiddenClass of the deleted
// attribute and hence avoid creation of its ancestors.
HiddenClass* cur = root_hcls;
int curidx = 0;
for (const auto& attr : new_attrs) {
if (curidx == new_attrwrapper_offset)
cur = cur->getAttrwrapperChild();
else
cur = cur->getOrMakeChild(attr);
curidx++;
}
return cur;
}
} // namespace pyston
// Copyright (c) 2014-2015 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_HIDDENCLASS_H
#define PYSTON_RUNTIME_HIDDENCLASS_H
#include <llvm/ADT/StringMap.h>
#include "Python.h"
#include "core/contiguous_map.h"
#include "core/types.h"
#include "gc/gc_alloc.h"
namespace pyston {
class HiddenClass : public GCAllocated<gc::GCKind::HIDDEN_CLASS> {
public:
// We have a couple different storage strategies for attributes, which
// are distinguished by having a different hidden class type.
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;
private:
HiddenClass(HCType type) : type(type) {}
HiddenClass(HiddenClass* parent)
: type(NORMAL), attr_offsets(parent->attr_offsets), attrwrapper_offset(parent->attrwrapper_offset) {
assert(parent->type == NORMAL);
}
// These fields only make sense for NORMAL or SINGLETON hidden classes:
llvm::DenseMap<BoxedString*, int> attr_offsets;
// If >= 0, is the offset where we stored an attrwrapper object
int attrwrapper_offset = -1;
// These are only for NORMAL hidden classes:
ContiguousMap<BoxedString*, HiddenClass*, llvm::DenseMap<BoxedString*, 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;
assert(!made);
made = true;
#endif
return new HiddenClass(NORMAL);
}
static HiddenClass* makeDictBacked() {
#ifndef NDEBUG
static bool made = false;
assert(!made);
made = true;
#endif
return new HiddenClass(DICT_BACKED);
}
void gc_visit(GCVisitor* visitor) {
// Visit children even for the dict-backed case, since children will just be empty
visitor->visitRange((void* const*)&children.vector()[0], (void* const*)&children.vector()[children.size()]);
visitor->visit(attrwrapper_child);
// We don't need to visit the keys of the 'children' map, since the children should have those as entries
// in the attr_offssets map.
// Also, if we have any children, we can skip scanning our attr_offsets map, since it will be a subset
// of our child's map.
if (children.empty())
for (auto p : attr_offsets)
visitor->visit(p.first);
}
// The total size of the attribute array. The slots in the attribute array may not correspond 1:1 to Python
// attributes.
int attributeArraySize() {
if (type == DICT_BACKED)
return 1;
ASSERT(type == NORMAL || type == SINGLETON, "%d", type);
int r = attr_offsets.size();
if (attrwrapper_offset != -1)
r += 1;
return r;
}
// The mapping from string attribute names to attribute offsets. There may be other objects in the attributes
// array.
// Only valid for NORMAL or SINGLETON hidden classes
const llvm::DenseMap<BoxedString*, int>& getStrAttrOffsets() {
assert(type == NORMAL || type == SINGLETON);
return attr_offsets;
}
// Only valid for NORMAL hidden classes:
HiddenClass* getOrMakeChild(BoxedString* attr);
// Only valid for NORMAL or SINGLETON hidden classes:
int getOffset(BoxedString* attr) {
assert(type == NORMAL || type == SINGLETON);
auto it = attr_offsets.find(attr);
if (it == attr_offsets.end())
return -1;
return it->second;
}
int getAttrwrapperOffset() {
assert(type == NORMAL || type == SINGLETON);
return attrwrapper_offset;
}
// Only valid for SINGLETON hidden classes:
void appendAttribute(BoxedString* attr);
void appendAttrwrapper();
void delAttribute(BoxedString* attr);
void addDependence(Rewriter* rewriter);
// Only valid for NORMAL hidden classes:
HiddenClass* getAttrwrapperChild();
// Only valid for NORMAL hidden classes:
HiddenClass* delAttrToMakeHC(BoxedString* attr);
};
}
#endif
......@@ -44,6 +44,7 @@
#include "runtime/file.h"
#include "runtime/float.h"
#include "runtime/generator.h"
#include "runtime/hiddenclass.h"
#include "runtime/ics.h"
#include "runtime/iterobject.h"
#include "runtime/long.h"
......@@ -581,117 +582,6 @@ const char* getNameOfClass(BoxedClass* cls) {
return cls->tp_name;
}
void HiddenClass::appendAttribute(BoxedString* attr) {
assert(attr->interned_state != SSTATE_NOT_INTERNED);
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(BoxedString* attr) {
assert(attr->interned_state != SSTATE_NOT_INTERNED);
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(BoxedString* attr) {
STAT_TIMER(t0, "us_timer_hiddenclass_getOrMakeChild", 0);
assert(attr->interned_state != SSTATE_NOT_INTERNED);
assert(type == NORMAL);
auto it = children.find(attr);
if (it != children.end())
return children.getMapped(it->second);
static StatCounter num_hclses("num_hidden_classes");
num_hclses.log();
HiddenClass* rtn = new HiddenClass(this);
rtn->attr_offsets[attr] = this->attributeArraySize();
this->children[attr] = rtn;
assert(rtn->attributeArraySize() == this->attributeArraySize() + 1);
return rtn;
}
HiddenClass* HiddenClass::getAttrwrapperChild() {
assert(type == NORMAL);
assert(attrwrapper_offset == -1);
if (!attrwrapper_child) {
HiddenClass* made = new HiddenClass(this);
made->attrwrapper_offset = this->attributeArraySize();
this->attrwrapper_child = made;
assert(made->attributeArraySize() == this->attributeArraySize() + 1);
}
return attrwrapper_child;
}
/**
* del attr from current HiddenClass, maintaining the order of the remaining attrs
*/
HiddenClass* HiddenClass::delAttrToMakeHC(BoxedString* attr) {
STAT_TIMER(t0, "us_timer_hiddenclass_delAttrToMakeHC", 0);
assert(attr->interned_state != SSTATE_NOT_INTERNED);
assert(type == NORMAL);
int idx = getOffset(attr);
assert(idx >= 0);
std::vector<BoxedString*> new_attrs(attributeArraySize() - 1);
for (auto it = attr_offsets.begin(); it != attr_offsets.end(); ++it) {
if (it->second < idx)
new_attrs[it->second] = it->first;
else if (it->second > idx) {
new_attrs[it->second - 1] = it->first;
}
}
int new_attrwrapper_offset = attrwrapper_offset;
if (new_attrwrapper_offset > idx)
new_attrwrapper_offset--;
// TODO we can first locate the parent HiddenClass of the deleted
// attribute and hence avoid creation of its ancestors.
HiddenClass* cur = root_hcls;
int curidx = 0;
for (const auto& attr : new_attrs) {
if (curidx == new_attrwrapper_offset)
cur = cur->getAttrwrapperChild();
else
cur = cur->getOrMakeChild(attr);
curidx++;
}
return cur;
}
size_t Box::getHCAttrsOffset() {
assert(cls->instancesHaveHCAttrs());
......
......@@ -38,6 +38,7 @@
#include "runtime/complex.h"
#include "runtime/dict.h"
#include "runtime/file.h"
#include "runtime/hiddenclass.h"
#include "runtime/ics.h"
#include "runtime/iterobject.h"
#include "runtime/list.h"
......
......@@ -327,123 +327,6 @@ static_assert(offsetof(pyston::BoxedHeapClass, as_sequence) == offsetof(PyHeapTy
static_assert(offsetof(pyston::BoxedHeapClass, as_buffer) == offsetof(PyHeapTypeObject, as_buffer), "");
static_assert(sizeof(pyston::BoxedHeapClass) == sizeof(PyHeapTypeObject), "");
class HiddenClass : public GCAllocated<gc::GCKind::HIDDEN_CLASS> {
public:
// We have a couple different storage strategies for attributes, which
// are distinguished by having a different hidden class type.
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;
private:
HiddenClass(HCType type) : type(type) {}
HiddenClass(HiddenClass* parent)
: type(NORMAL), attr_offsets(parent->attr_offsets), attrwrapper_offset(parent->attrwrapper_offset) {
assert(parent->type == NORMAL);
}
// These fields only make sense for NORMAL or SINGLETON hidden classes:
llvm::DenseMap<BoxedString*, int> attr_offsets;
// If >= 0, is the offset where we stored an attrwrapper object
int attrwrapper_offset = -1;
// These are only for NORMAL hidden classes:
ContiguousMap<BoxedString*, HiddenClass*, llvm::DenseMap<BoxedString*, 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;
assert(!made);
made = true;
#endif
return new HiddenClass(NORMAL);
}
static HiddenClass* makeDictBacked() {
#ifndef NDEBUG
static bool made = false;
assert(!made);
made = true;
#endif
return new HiddenClass(DICT_BACKED);
}
void gc_visit(GCVisitor* visitor) {
// Visit children even for the dict-backed case, since children will just be empty
visitor->visitRange((void* const*)&children.vector()[0], (void* const*)&children.vector()[children.size()]);
visitor->visit(attrwrapper_child);
// We don't need to visit the keys of the 'children' map, since the children should have those as entries
// in the attr_offssets map.
// Also, if we have any children, we can skip scanning our attr_offsets map, since it will be a subset
// of our child's map.
if (children.empty())
for (auto p : attr_offsets)
visitor->visit(p.first);
}
// The total size of the attribute array. The slots in the attribute array may not correspond 1:1 to Python
// attributes.
int attributeArraySize() {
if (type == DICT_BACKED)
return 1;
ASSERT(type == NORMAL || type == SINGLETON, "%d", type);
int r = attr_offsets.size();
if (attrwrapper_offset != -1)
r += 1;
return r;
}
// The mapping from string attribute names to attribute offsets. There may be other objects in the attributes
// array.
// Only valid for NORMAL or SINGLETON hidden classes
const llvm::DenseMap<BoxedString*, int>& getStrAttrOffsets() {
assert(type == NORMAL || type == SINGLETON);
return attr_offsets;
}
// Only valid for NORMAL hidden classes:
HiddenClass* getOrMakeChild(BoxedString* attr);
// Only valid for NORMAL or SINGLETON hidden classes:
int getOffset(BoxedString* attr) {
assert(type == NORMAL || type == SINGLETON);
auto it = attr_offsets.find(attr);
if (it == attr_offsets.end())
return -1;
return it->second;
}
int getAttrwrapperOffset() {
assert(type == NORMAL || type == SINGLETON);
return attrwrapper_offset;
}
// Only valid for SINGLETON hidden classes:
void appendAttribute(BoxedString* attr);
void appendAttrwrapper();
void delAttribute(BoxedString* attr);
void addDependence(Rewriter* rewriter);
// Only valid for NORMAL hidden classes:
HiddenClass* getAttrwrapperChild();
// Only valid for NORMAL hidden classes:
HiddenClass* delAttrToMakeHC(BoxedString* attr);
};
class BoxedInt : public Box {
public:
int64_t n;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment