#pragma once
#include "JSCJSValue.h"
#include "StructureIDTable.h"
#include <wtf/Gigacage.h>
#include <wtf/Lock.h>
namespace JSC {
class JSCell;
class VM;
namespace Integrity {
enum class AuditLevel {
None,
Minimal,
Full,
Random,
};
#ifdef NDEBUG
static constexpr AuditLevel DefaultAuditLevel = AuditLevel::None;
#else
static constexpr AuditLevel DefaultAuditLevel = AuditLevel::Random;
#endif
class Random {
public:
Random(VM&);
ALWAYS_INLINE bool shouldAudit(VM&);
private:
JS_EXPORT_PRIVATE bool reloadAndCheckShouldAuditSlow(VM&);
uint64_t m_triggerBits;
Lock m_lock;
static constexpr int numberOfTriggerBits = (sizeof(m_triggerBits) * CHAR_BIT) - 1;
};
ALWAYS_INLINE void auditCellRandomly(VM&, JSCell*);
ALWAYS_INLINE void auditCellMinimally(VM&, JSCell*);
JS_EXPORT_PRIVATE void auditCellMinimallySlow(VM&, JSCell*);
JS_EXPORT_PRIVATE void auditCellFully(VM&, JSCell*);
template<AuditLevel = AuditLevel::Random, typename T>
ALWAYS_INLINE void auditCell(VM&, T) { }
template<AuditLevel auditLevel = DefaultAuditLevel>
ALWAYS_INLINE void auditCell(VM& vm, JSCell* cell)
{
switch (auditLevel) {
case AuditLevel::None:
return;
case AuditLevel::Minimal:
return auditCellMinimally(vm, cell);
case AuditLevel::Full:
return auditCellFully(vm, cell);
case AuditLevel::Random:
return auditCellRandomly(vm, cell);
}
}
template<AuditLevel auditLevel = DefaultAuditLevel>
ALWAYS_INLINE void auditCell(VM& vm, JSValue value)
{
if (auditLevel == AuditLevel::None)
return;
if (value.isCell())
auditCell<auditLevel>(vm, value.asCell());
}
ALWAYS_INLINE void auditStructureID(StructureIDTable&, StructureID);
ALWAYS_INLINE void auditStructureID(VM&, StructureID);
}
}