#include "config.h"
#include "SymbolTable.h"
#include "JSDestructibleObject.h"
#include "JSCInlines.h"
#include "SlotVisitorInlines.h"
#include "VariableWatchpointSetInlines.h"
namespace JSC {
const ClassInfo SymbolTable::s_info = { "SymbolTable", 0, 0, 0, CREATE_METHOD_TABLE(SymbolTable) };
SymbolTableEntry& SymbolTableEntry::copySlow(const SymbolTableEntry& other)
{
ASSERT(other.isFat());
FatEntry* newFatEntry = new FatEntry(*other.fatEntry());
freeFatEntry();
m_bits = bitwise_cast<intptr_t>(newFatEntry);
return *this;
}
void SymbolTable::destroy(JSCell* cell)
{
SymbolTable* thisObject = jsCast<SymbolTable*>(cell);
thisObject->SymbolTable::~SymbolTable();
}
void SymbolTableEntry::freeFatEntrySlow()
{
ASSERT(isFat());
delete fatEntry();
}
JSValue SymbolTableEntry::inferredValue()
{
if (!isFat())
return JSValue();
return fatEntry()->m_watchpoints->inferredValue();
}
void SymbolTableEntry::prepareToWatch(SymbolTable* symbolTable)
{
FatEntry* entry = inflate();
if (entry->m_watchpoints)
return;
entry->m_watchpoints = adoptRef(new VariableWatchpointSet(*symbolTable));
}
void SymbolTableEntry::addWatchpoint(Watchpoint* watchpoint)
{
fatEntry()->m_watchpoints->add(watchpoint);
}
void SymbolTableEntry::notifyWriteSlow(VM& vm, JSValue value)
{
VariableWatchpointSet* watchpoints = fatEntry()->m_watchpoints.get();
if (!watchpoints)
return;
watchpoints->notifyWrite(vm, value);
}
SymbolTableEntry::FatEntry* SymbolTableEntry::inflateSlow()
{
FatEntry* entry = new FatEntry(m_bits);
m_bits = bitwise_cast<intptr_t>(entry);
return entry;
}
SymbolTable::SymbolTable(VM& vm)
: JSCell(vm, vm.symbolTableStructure.get())
, m_parameterCountIncludingThis(0)
, m_usesNonStrictEval(false)
, m_captureStart(0)
, m_captureEnd(0)
, m_functionEnteredOnce(ClearWatchpoint)
{
}
SymbolTable::~SymbolTable() { }
void SymbolTable::visitChildren(JSCell* thisCell, SlotVisitor& visitor)
{
SymbolTable* thisSymbolTable = jsCast<SymbolTable*>(thisCell);
if (!thisSymbolTable->m_watchpointCleanup) {
thisSymbolTable->m_watchpointCleanup =
std::make_unique<WatchpointCleanup>(thisSymbolTable);
}
visitor.addUnconditionalFinalizer(thisSymbolTable->m_watchpointCleanup.get());
}
SymbolTable::WatchpointCleanup::WatchpointCleanup(SymbolTable* symbolTable)
: m_symbolTable(symbolTable)
{
}
SymbolTable::WatchpointCleanup::~WatchpointCleanup() { }
void SymbolTable::WatchpointCleanup::finalizeUnconditionally()
{
Map::iterator iter = m_symbolTable->m_map.begin();
Map::iterator end = m_symbolTable->m_map.end();
for (; iter != end; ++iter) {
if (VariableWatchpointSet* set = iter->value.watchpointSet())
set->finalizeUnconditionally();
}
}
SymbolTable* SymbolTable::cloneCapturedNames(VM& vm)
{
SymbolTable* result = SymbolTable::create(vm);
result->m_parameterCountIncludingThis = m_parameterCountIncludingThis;
result->m_usesNonStrictEval = m_usesNonStrictEval;
result->m_captureStart = m_captureStart;
result->m_captureEnd = m_captureEnd;
for (auto iter = m_map.begin(), end = m_map.end(); iter != end; ++iter) {
if (!isCaptured(iter->value.getIndex()))
continue;
result->m_map.add(
iter->key,
SymbolTableEntry(iter->value.getIndex(), iter->value.getAttributes()));
}
if (m_slowArguments) {
result->m_slowArguments = std::make_unique<SlowArgument[]>(parameterCount());
for (unsigned i = parameterCount(); i--;)
result->m_slowArguments[i] = m_slowArguments[i];
}
return result;
}
}