Skip to content

Commit

Permalink
Improve performance with large object
Browse files Browse the repository at this point in the history
Signed-off-by: Seonghyun Kim <[email protected]>
  • Loading branch information
ksh8281 authored and clover2123 committed Dec 7, 2023
1 parent 5d59757 commit 59a626b
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 25 deletions.
48 changes: 34 additions & 14 deletions src/runtime/ObjectStructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,30 @@ void* ObjectStructureWithoutTransition::operator new(size_t size)

std::pair<size_t, Optional<const ObjectStructureItem*>> ObjectStructureWithoutTransition::findProperty(const ObjectStructurePropertyName& s)
{
if (m_properties->size() && m_lastFoundPropertyName == s) {
uint16_t lastIndex = lastFoundPropertyIndex();
if (lastIndex == std::numeric_limits<uint16_t>::max()) {
return std::make_pair(std::numeric_limits<size_t>::max(), Optional<const ObjectStructureItem*>());
}
return std::make_pair(lastIndex, &(*m_properties)[lastIndex]);
}
m_lastFoundPropertyName = s;
setLastFoundPropertyIndex(std::numeric_limits<uint16_t>::max());
size_t size = m_properties->size();

if (LIKELY(s.hasAtomicString())) {
if (LIKELY(!m_hasNonAtomicPropertyName)) {
for (size_t i = 0; i < size; i++) {
if ((*m_properties)[i].m_propertyName.rawValue() == s.rawValue()) {
setLastFoundPropertyIndex(i);
return std::make_pair(i, &(*m_properties)[i]);
}
}
} else {
AtomicString as = s.asAtomicString();
for (size_t i = 0; i < size; i++) {
if ((*m_properties)[i].m_propertyName == as) {
setLastFoundPropertyIndex(i);
return std::make_pair(i, &(*m_properties)[i]);
}
}
Expand All @@ -71,13 +82,15 @@ std::pair<size_t, Optional<const ObjectStructureItem*>> ObjectStructureWithoutTr
if (m_hasSymbolPropertyName) {
for (size_t i = 0; i < size; i++) {
if ((*m_properties)[i].m_propertyName == s) {
setLastFoundPropertyIndex(i);
return std::make_pair(i, &(*m_properties)[i]);
}
}
}
} else {
for (size_t i = 0; i < size; i++) {
if ((*m_properties)[i].m_propertyName == s) {
setLastFoundPropertyIndex(i);
return std::make_pair(i, &(*m_properties)[i]);
}
}
Expand Down Expand Up @@ -121,7 +134,7 @@ ObjectStructure* ObjectStructureWithoutTransition::addProperty(const ObjectStruc


if (propertiesForNewStructure->size() > ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE) {
newStructure = new ObjectStructureWithMap(propertiesForNewStructure, ObjectStructureWithMap::createPropertyNameMap(propertiesForNewStructure), nameIsIndexString, nameIsSymbol, hasEnumerableProperty);
newStructure = new ObjectStructureWithMap(propertiesForNewStructure, nullptr, nameIsIndexString, nameIsSymbol, hasEnumerableProperty);
} else {
newStructure = new ObjectStructureWithoutTransition(propertiesForNewStructure, nameIsIndexString, nameIsSymbol, hasNonAtomicName, hasEnumerableProperty);
}
Expand Down Expand Up @@ -367,11 +380,14 @@ void* ObjectStructureWithMap::operator new(size_t size)

std::pair<size_t, Optional<const ObjectStructureItem*>> ObjectStructureWithMap::findProperty(const ObjectStructurePropertyName& s)
{
auto iter = m_propertyNameMap->find(s);
if (iter == m_propertyNameMap->end()) {
if (!m_propertyNameMap) {
m_propertyNameMap = createPropertyNameMap(m_properties);
}
auto idx = m_propertyNameMap->find(s);
if (idx == SIZE_MAX) {
return std::make_pair(SIZE_MAX, Optional<const ObjectStructureItem*>());
}
return std::make_pair(iter->second, &(m_properties->data()[iter->second]));
return std::make_pair(idx, &(m_properties->data()[idx]));
}

const ObjectStructureItem& ObjectStructureWithMap::readProperty(size_t idx)
Expand All @@ -396,19 +412,23 @@ ObjectStructure* ObjectStructureWithMap::addProperty(const ObjectStructureProper
bool hasSymbol = m_hasSymbolPropertyName ? true : name.isSymbol();
bool hasEnumerableProperty = m_hasEnumerableProperty ? true : desc.isEnumerable();

ObjectStructureItemVector* newProperties = m_properties;
PropertyNameMap* newPropertyNameMap = m_propertyNameMap;
ObjectStructureItemVector* newProperties;
Optional<PropertyNameMapWithCache*> newPropertyNameMap;

if (m_isReferencedByInlineCache) {
newProperties = new ObjectStructureItemVector(*m_properties);
newPropertyNameMap = new (GC) PropertyNameMap(*m_propertyNameMap);
newProperties = new ObjectStructureItemVector(*m_properties, newItem);
} else {
newProperties = m_properties;
newProperties->push_back(newItem);
m_properties = nullptr;
m_propertyNameMap = nullptr;
if (m_propertyNameMap) {
m_propertyNameMap->insert(name, newProperties->size() - 1);
ASSERT(m_propertyNameMap->size() == newProperties->size());
newPropertyNameMap = m_propertyNameMap;
m_propertyNameMap = nullptr;
}
}

newPropertyNameMap->insert(std::make_pair(name, newProperties->size()));
newProperties->push_back(newItem);
ObjectStructure* newStructure = new ObjectStructureWithMap(newProperties, newPropertyNameMap, nameIsIndexString, hasSymbol, hasEnumerableProperty);
return newStructure;
}
Expand Down Expand Up @@ -441,7 +461,7 @@ ObjectStructure* ObjectStructureWithMap::removeProperty(size_t pIndex)
m_propertyNameMap = nullptr;
}
if (newProperties->size() > ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE) {
return new ObjectStructureWithMap(newProperties, ObjectStructureWithMap::createPropertyNameMap(newProperties), hasIndexString, hasSymbol, hasEnumerableProperty);
return new ObjectStructureWithMap(newProperties, nullptr, hasIndexString, hasSymbol, hasEnumerableProperty);
} else {
return new ObjectStructureWithoutTransition(newProperties, hasIndexString, hasSymbol, hasNonAtomicName, hasEnumerableProperty);
}
Expand All @@ -450,11 +470,11 @@ ObjectStructure* ObjectStructureWithMap::removeProperty(size_t pIndex)
ObjectStructure* ObjectStructureWithMap::replacePropertyDescriptor(size_t idx, const ObjectStructurePropertyDescriptor& newDesc)
{
ObjectStructureItemVector* newProperties = m_properties;
PropertyNameMap* newPropertyNameMap = m_propertyNameMap;
auto newPropertyNameMap = m_propertyNameMap;

if (m_isReferencedByInlineCache) {
newProperties = new ObjectStructureItemVector(*m_properties);
newPropertyNameMap = new (GC) PropertyNameMap(*m_propertyNameMap);
newPropertyNameMap = nullptr;
} else {
m_properties = nullptr;
m_propertyNameMap = nullptr;
Expand Down
108 changes: 97 additions & 11 deletions src/runtime/ObjectStructure.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class ObjectStructureItemVector : public Vector<ObjectStructureItem, GCUtil::gc_

#if defined(ESCARGOT_SMALL_CONFIG)
#ifndef ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE
#define ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE 256
#define ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE 2048
#endif
#ifndef ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MODE_MAX_SIZE
#define ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MODE_MAX_SIZE 12
Expand All @@ -112,16 +112,18 @@ class ObjectStructureItemVector : public Vector<ObjectStructureItem, GCUtil::gc_
#endif
#else
#ifndef ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE
#define ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE 96
#define ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE 512
#endif
#ifndef ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MODE_MAX_SIZE
#define ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MODE_MAX_SIZE 48
#define ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MODE_MAX_SIZE 36
#endif
#ifndef ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MAP_MIN_SIZE
#define ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MAP_MIN_SIZE 32
#endif
#endif

COMPILE_ASSERT(ESCARGOT_OBJECT_STRUCTURE_ACCESS_CACHE_BUILD_MIN_SIZE < 65536, "");

class ObjectStructure : public gc {
public:
virtual ~ObjectStructure() {}
Expand Down Expand Up @@ -220,6 +222,12 @@ class ObjectStructureWithoutTransition : public ObjectStructure {
hasSymbolPropertyName, hasNonAtomicPropertyName, hasEnumerableProperty)
, m_properties(properties)
{
size_t propertyCount = m_properties->size();
ASSERT(propertyCount < 65535);
if (LIKELY(propertyCount)) {
m_lastFoundPropertyName = m_properties->back().m_propertyName;
setLastFoundPropertyIndex(propertyCount - 1);
}
}

virtual std::pair<size_t, Optional<const ObjectStructureItem*>> findProperty(const ObjectStructurePropertyName& s) override;
Expand All @@ -239,8 +247,27 @@ class ObjectStructureWithoutTransition : public ObjectStructure {
void* operator new(size_t size);
void* operator new[](size_t size) = delete;

void setLastFoundPropertyIndex(uint16_t s)
{
uint8_t* p = reinterpret_cast<uint8_t*>(&s);
m_transitionTableVectorBufferSize = *p;
p++;
m_transitionTableVectorBufferCapacity = *p;
}

uint16_t lastFoundPropertyIndex()
{
uint16_t s;
uint8_t* p = reinterpret_cast<uint8_t*>(&s);
*p = m_transitionTableVectorBufferSize;
p++;
*p = m_transitionTableVectorBufferCapacity;
return s;
}

private:
ObjectStructureItemVector* m_properties;
ObjectStructurePropertyName m_lastFoundPropertyName;
};

class ObjectStructureWithTransition : public ObjectStructure {
Expand Down Expand Up @@ -290,9 +317,70 @@ class ObjectStructureWithTransition : public ObjectStructure {
COMPILE_ASSERT(ESCARGOT_OBJECT_STRUCTURE_TRANSITION_MAP_MIN_SIZE <= 32, "");
COMPILE_ASSERT(sizeof(ObjectStructureWithTransition) == sizeof(size_t) * 5, "");

class PropertyNameMapWithCache : protected PropertyNameMap, public gc {
struct CacheItem {
ObjectStructurePropertyName m_name;
size_t m_index;
CacheItem()
: m_name()
, m_index(SIZE_MAX)
{
}
};

public:
PropertyNameMapWithCache()
: PropertyNameMap()
{
}

void reserve(size_t t)
{
PropertyNameMap::reserve(t);
}

size_t size() const
{
return PropertyNameMap::size();
}

void insert(const ObjectStructurePropertyName& name, size_t idx)
{
m_lastItem.m_name = name;
m_lastItem.m_index = idx;
PropertyNameMap::insert(std::make_pair(name, idx));
}

size_t find(const ObjectStructurePropertyName& name)
{
if (name == m_lastItem.m_name) {
#ifndef NDEBUG
auto iter = PropertyNameMap::find(name);
if (iter == end()) {
ASSERT(m_lastItem.m_index == SIZE_MAX);
} else {
ASSERT(m_lastItem.m_index == m_lastItem.m_index);
}
#endif
return m_lastItem.m_index;
}
m_lastItem.m_name = name;
auto iter = PropertyNameMap::find(name);
if (iter == end()) {
m_lastItem.m_index = SIZE_MAX;
return SIZE_MAX;
}
m_lastItem.m_index = iter->second;
return iter->second;
}

private:
CacheItem m_lastItem;
};

class ObjectStructureWithMap : public ObjectStructure {
public:
ObjectStructureWithMap(ObjectStructureItemVector* properties, PropertyNameMap* map, bool hasIndexPropertyName, bool hasSymbolPropertyName, bool hasEnumerableProperty)
ObjectStructureWithMap(ObjectStructureItemVector* properties, Optional<PropertyNameMapWithCache*> map, bool hasIndexPropertyName, bool hasSymbolPropertyName, bool hasEnumerableProperty)
: ObjectStructure(hasIndexPropertyName,
hasSymbolPropertyName, hasEnumerableProperty)
, m_properties(properties)
Expand All @@ -312,7 +400,6 @@ class ObjectStructureWithMap : public ObjectStructure {
newProperties->at(properties.size()) = newItem;

m_properties = newProperties;
m_propertyNameMap = ObjectStructureWithMap::createPropertyNameMap(newProperties);
}

ObjectStructureWithMap(bool hasIndexPropertyName, bool hasSymbolPropertyName, bool hasEnumerableProperty, const ObjectStructureItemTightVector& properties)
Expand All @@ -325,7 +412,6 @@ class ObjectStructureWithMap : public ObjectStructure {
memcpy(newProperties->data(), properties.data(), properties.size() * sizeof(ObjectStructureItem));

m_properties = newProperties;
m_propertyNameMap = ObjectStructureWithMap::createPropertyNameMap(newProperties);
}

template <typename ItemVector>
Expand All @@ -334,7 +420,6 @@ class ObjectStructureWithMap : public ObjectStructure {
hasSymbolPropertyName, hasEnumerableProperty)
{
m_properties = new ObjectStructureItemVector(std::move(properties));
m_propertyNameMap = ObjectStructureWithMap::createPropertyNameMap(m_properties);
}

virtual std::pair<size_t, Optional<const ObjectStructureItem*>> findProperty(const ObjectStructurePropertyName& s) override;
Expand All @@ -355,20 +440,21 @@ class ObjectStructureWithMap : public ObjectStructure {
void* operator new[](size_t size) = delete;

template <typename SourceVectorType>
static PropertyNameMap* createPropertyNameMap(SourceVectorType* from)
static PropertyNameMapWithCache* createPropertyNameMap(SourceVectorType* from)
{
PropertyNameMap* map = new (GC) PropertyNameMap();
PropertyNameMapWithCache* map = new PropertyNameMapWithCache();

map->reserve(from->size());
for (size_t i = 0; i < from->size(); i++) {
map->insert(std::make_pair((*from)[i].m_propertyName, i));
map->insert((*from)[i].m_propertyName, i);
}

return map;
}

private:
ObjectStructureItemVector* m_properties;
PropertyNameMap* m_propertyNameMap;
Optional<PropertyNameMapWithCache*> m_propertyNameMap;
};
} // namespace Escargot

Expand Down

0 comments on commit 59a626b

Please sign in to comment.