mirror of
https://github.com/darlinghq/darling-JavaScriptCore.git
synced 2024-11-23 04:09:40 +00:00
213 lines
8.5 KiB
C++
213 lines
8.5 KiB
C++
/*
|
|
* Copyright (C) 2009-2019 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "CommonIdentifiers.h"
|
|
#include "Identifier.h"
|
|
#include <array>
|
|
#include <type_traits>
|
|
#include <wtf/SegmentedVector.h>
|
|
|
|
namespace JSC {
|
|
|
|
class ParserArenaDeletable;
|
|
|
|
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(IdentifierArena);
|
|
class IdentifierArena {
|
|
WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(IdentifierArena);
|
|
public:
|
|
IdentifierArena()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
template <typename T>
|
|
ALWAYS_INLINE const Identifier& makeIdentifier(VM&, const T* characters, size_t length);
|
|
ALWAYS_INLINE const Identifier& makeEmptyIdentifier(VM&);
|
|
ALWAYS_INLINE const Identifier& makeIdentifierLCharFromUChar(VM&, const UChar* characters, size_t length);
|
|
ALWAYS_INLINE const Identifier& makeIdentifier(VM&, SymbolImpl*);
|
|
|
|
const Identifier& makeBigIntDecimalIdentifier(VM&, const Identifier&, uint8_t radix);
|
|
const Identifier& makeNumericIdentifier(VM&, double number);
|
|
const Identifier& makePrivateIdentifier(VM&, ASCIILiteral, unsigned);
|
|
|
|
public:
|
|
static const int MaximumCachableCharacter = 128;
|
|
typedef SegmentedVector<Identifier, 64> IdentifierVector;
|
|
void clear()
|
|
{
|
|
m_identifiers.clear();
|
|
for (int i = 0; i < MaximumCachableCharacter; i++)
|
|
m_shortIdentifiers[i] = nullptr;
|
|
for (int i = 0; i < MaximumCachableCharacter; i++)
|
|
m_recentIdentifiers[i] = nullptr;
|
|
}
|
|
|
|
private:
|
|
IdentifierVector m_identifiers;
|
|
std::array<Identifier*, MaximumCachableCharacter> m_shortIdentifiers;
|
|
std::array<Identifier*, MaximumCachableCharacter> m_recentIdentifiers;
|
|
};
|
|
|
|
template <typename T>
|
|
ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(VM& vm, const T* characters, size_t length)
|
|
{
|
|
if (!length)
|
|
return vm.propertyNames->emptyIdentifier;
|
|
if (characters[0] >= MaximumCachableCharacter) {
|
|
m_identifiers.append(Identifier::fromString(vm, characters, length));
|
|
return m_identifiers.last();
|
|
}
|
|
if (length == 1) {
|
|
if (Identifier* ident = m_shortIdentifiers[characters[0]])
|
|
return *ident;
|
|
m_identifiers.append(Identifier::fromString(vm, characters, length));
|
|
m_shortIdentifiers[characters[0]] = &m_identifiers.last();
|
|
return m_identifiers.last();
|
|
}
|
|
Identifier* ident = m_recentIdentifiers[characters[0]];
|
|
if (ident && Identifier::equal(ident->impl(), characters, length))
|
|
return *ident;
|
|
m_identifiers.append(Identifier::fromString(vm, characters, length));
|
|
m_recentIdentifiers[characters[0]] = &m_identifiers.last();
|
|
return m_identifiers.last();
|
|
}
|
|
|
|
ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(VM&, SymbolImpl* symbol)
|
|
{
|
|
ASSERT(symbol);
|
|
m_identifiers.append(Identifier::fromUid(*symbol));
|
|
return m_identifiers.last();
|
|
}
|
|
|
|
ALWAYS_INLINE const Identifier& IdentifierArena::makeEmptyIdentifier(VM& vm)
|
|
{
|
|
return vm.propertyNames->emptyIdentifier;
|
|
}
|
|
|
|
ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifierLCharFromUChar(VM& vm, const UChar* characters, size_t length)
|
|
{
|
|
if (!length)
|
|
return vm.propertyNames->emptyIdentifier;
|
|
if (characters[0] >= MaximumCachableCharacter) {
|
|
m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length));
|
|
return m_identifiers.last();
|
|
}
|
|
if (length == 1) {
|
|
if (Identifier* ident = m_shortIdentifiers[characters[0]])
|
|
return *ident;
|
|
m_identifiers.append(Identifier::fromString(vm, characters, length));
|
|
m_shortIdentifiers[characters[0]] = &m_identifiers.last();
|
|
return m_identifiers.last();
|
|
}
|
|
Identifier* ident = m_recentIdentifiers[characters[0]];
|
|
if (ident && Identifier::equal(ident->impl(), characters, length))
|
|
return *ident;
|
|
m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length));
|
|
m_recentIdentifiers[characters[0]] = &m_identifiers.last();
|
|
return m_identifiers.last();
|
|
}
|
|
|
|
inline const Identifier& IdentifierArena::makeNumericIdentifier(VM& vm, double number)
|
|
{
|
|
// FIXME: Why doesn't this use the Identifier::from overload that takes a double?
|
|
// Seems we are missing out on multiple optimizations by not using it.
|
|
m_identifiers.append(Identifier::fromString(vm, String::number(number)));
|
|
return m_identifiers.last();
|
|
}
|
|
|
|
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ParserArena);
|
|
|
|
class ParserArena {
|
|
WTF_MAKE_NONCOPYABLE(ParserArena);
|
|
public:
|
|
ParserArena();
|
|
~ParserArena();
|
|
|
|
void swap(ParserArena& otherArena)
|
|
{
|
|
std::swap(m_freeableMemory, otherArena.m_freeableMemory);
|
|
std::swap(m_freeablePoolEnd, otherArena.m_freeablePoolEnd);
|
|
m_identifierArena.swap(otherArena.m_identifierArena);
|
|
m_freeablePools.swap(otherArena.m_freeablePools);
|
|
m_deletableObjects.swap(otherArena.m_deletableObjects);
|
|
}
|
|
|
|
void* allocateFreeable(size_t size)
|
|
{
|
|
ASSERT(size);
|
|
ASSERT(size <= freeablePoolSize);
|
|
size_t alignedSize = alignSize(size);
|
|
ASSERT(alignedSize <= freeablePoolSize);
|
|
if (UNLIKELY(static_cast<size_t>(m_freeablePoolEnd - m_freeableMemory) < alignedSize))
|
|
allocateFreeablePool();
|
|
void* block = m_freeableMemory;
|
|
m_freeableMemory += alignedSize;
|
|
return block;
|
|
}
|
|
|
|
template<typename T, typename = std::enable_if_t<std::is_base_of<ParserArenaDeletable, T>::value>>
|
|
void* allocateDeletable(size_t size)
|
|
{
|
|
// T may extend ParserArenaDeletable via multiple inheritance, but not as T's first
|
|
// base class. m_deletableObjects is expecting pointers to objects of the shape of
|
|
// ParserArenaDeletable. We ensure this by allocating T, and casting it to
|
|
// ParserArenaDeletable to get the correct pointer to append to m_deletableObjects.
|
|
T* instance = static_cast<T*>(allocateFreeable(size));
|
|
ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(instance);
|
|
m_deletableObjects.append(deletable);
|
|
return instance;
|
|
}
|
|
|
|
IdentifierArena& identifierArena()
|
|
{
|
|
if (UNLIKELY (!m_identifierArena))
|
|
m_identifierArena = makeUnique<IdentifierArena>();
|
|
return *m_identifierArena;
|
|
}
|
|
|
|
private:
|
|
static const size_t freeablePoolSize = 8000;
|
|
|
|
static size_t alignSize(size_t size)
|
|
{
|
|
return (size + sizeof(WTF::AllocAlignmentInteger) - 1) & ~(sizeof(WTF::AllocAlignmentInteger) - 1);
|
|
}
|
|
|
|
void* freeablePool();
|
|
void allocateFreeablePool();
|
|
void deallocateObjects();
|
|
|
|
char* m_freeableMemory;
|
|
char* m_freeablePoolEnd;
|
|
|
|
std::unique_ptr<IdentifierArena> m_identifierArena;
|
|
Vector<void*> m_freeablePools;
|
|
Vector<ParserArenaDeletable*> m_deletableObjects;
|
|
};
|
|
|
|
} // namespace JSC
|