Skip to content

Commit

Permalink
Implement packing local variable and constant data on 64-bit if stack…
Browse files Browse the repository at this point in the history
… usage is high

Signed-off-by: Seonghyun Kim <[email protected]>
  • Loading branch information
ksh8281 committed Sep 4, 2023
1 parent 78a7a46 commit b41b602
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/Walrus.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ if (f.type == Type::B) { puts("failed in msvc."); }
std::unique_ptr<uint8_t[]> Result##HolderWhenUsingMalloc; \
size_t bytes##Result = (Bytes); \
Type* Result; \
if (LIKELY(bytes##Result < 512)) { \
if (LIKELY(bytes##Result < 2048)) { \
Result = (Type*)alloca(bytes##Result); \
} else { \
Result##HolderWhenUsingMalloc = std::unique_ptr<uint8_t[]>(new uint8_t[bytes##Result]); \
Expand Down
79 changes: 66 additions & 13 deletions src/parser/WASMParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate {
bool m_inPreprocess;
WASMBinaryReader& m_reader;
std::vector<LocalVariableInfo> m_localVariableInfo;
// <ConstantValue, reference count or position>
std::vector<std::pair<Walrus::Value, size_t>> m_constantData;
};

Expand Down Expand Up @@ -593,7 +594,7 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate {
m_localInfo.push_back(LocalInfo(m_currentFunctionType->param()[i], pos));
pos += Walrus::valueStackAllocatedSize(m_localInfo[i].m_valueType);
}
m_currentFunction->m_requiredStackSizeDueToParameterAndLocal = m_initialFunctionStackSize = m_functionStackSizeSoFar = m_currentFunctionType->paramStackSize();
m_initialFunctionStackSize = m_functionStackSizeSoFar = m_currentFunctionType->paramStackSize();
m_currentFunction->m_requiredStackSize = std::max(
m_currentFunction->m_requiredStackSize, m_functionStackSizeSoFar);
}
Expand Down Expand Up @@ -977,7 +978,6 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate {
auto sz = Walrus::valueStackAllocatedSize(wType);
m_initialFunctionStackSize += sz;
m_functionStackSizeSoFar += sz;
m_currentFunction->m_requiredStackSizeDueToParameterAndLocal += sz;
count--;
}
m_currentFunction->m_requiredStackSize = std::max(
Expand Down Expand Up @@ -1011,7 +1011,64 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate {
m_vmStack.clear();

m_preprocessData.organizeData();
// init local if needs

// set const variables position
for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) {
auto constType = m_preprocessData.m_constantData[i].first.type();
m_preprocessData.m_constantData[i].second = m_initialFunctionStackSize;
m_initialFunctionStackSize += Walrus::valueStackAllocatedSize(constType);
}

#if defined(WALRUS_64)
#ifndef WALRUS_ENABLE_LOCAL_VARIABLE_PACKING_MIN_SIZE
#define WALRUS_ENABLE_LOCAL_VARIABLE_PACKING_MIN_SIZE 64
#endif
// pack local variables if needs
constexpr size_t enableLocalVaraiblePackingMinSize = WALRUS_ENABLE_LOCAL_VARIABLE_PACKING_MIN_SIZE;
if (m_initialFunctionStackSize >= enableLocalVaraiblePackingMinSize) {
m_initialFunctionStackSize = m_currentFunctionType->paramStackSize();
// put already aligned variables first
for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) {
auto& info = m_localInfo[i];
if (Walrus::hasCPUWordAlingedSize(info.m_valueType) || needsCPUWordAlingedAddress(info.m_valueType)) {
info.m_position = m_initialFunctionStackSize;
m_initialFunctionStackSize += Walrus::valueStackAllocatedSize(info.m_valueType);
}
}
for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) {
auto constType = m_preprocessData.m_constantData[i].first.type();
if (Walrus::hasCPUWordAlingedSize(constType) || needsCPUWordAlingedAddress(constType)) {
m_preprocessData.m_constantData[i].second = m_initialFunctionStackSize;
m_initialFunctionStackSize += Walrus::valueStackAllocatedSize(constType);
}
}

// pack rest values
for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) {
auto& info = m_localInfo[i];
if (!Walrus::hasCPUWordAlingedSize(info.m_valueType) && !needsCPUWordAlingedAddress(info.m_valueType)) {
info.m_position = m_initialFunctionStackSize;
m_initialFunctionStackSize += Walrus::valueSize(info.m_valueType);
}
}
for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) {
auto constType = m_preprocessData.m_constantData[i].first.type();
if (!Walrus::hasCPUWordAlingedSize(constType) && !needsCPUWordAlingedAddress(constType)) {
m_preprocessData.m_constantData[i].second = m_initialFunctionStackSize;
m_initialFunctionStackSize += Walrus::valueSize(constType);
}
}

if (m_initialFunctionStackSize % sizeof(size_t)) {
m_initialFunctionStackSize += (sizeof(size_t) - m_initialFunctionStackSize % sizeof(size_t));
}
}
#endif

m_functionStackSizeSoFar = m_initialFunctionStackSize;
m_currentFunction->m_requiredStackSize = m_functionStackSizeSoFar;

// Explicit init local variable if needs
for (size_t i = m_currentFunctionType->param().size(); i < m_localInfo.size(); i++) {
if (m_preprocessData.m_localVariableInfo[i].m_needsExplicitInitOnStartup) {
auto localPos = m_localInfo[i].m_position;
Expand All @@ -1028,13 +1085,16 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate {
pushByteCode(Walrus::Const128(localPos, empty), WASMOpcode::V128ConstOpcode);
}
}
#if !defined(NDEBUG)
m_currentFunction->m_localDebugData.push_back(m_localInfo[i].m_position);
#endif
}

// init constant space
for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) {
const auto& constValue = m_preprocessData.m_constantData[i].first;
auto constType = m_preprocessData.m_constantData[i].first.type();
auto constPos = m_initialFunctionStackSize;
auto constPos = m_preprocessData.m_constantData[i].second;
size_t constSize = Walrus::valueSize(constType);

uint8_t constantBuffer[16];
Expand All @@ -1047,15 +1107,10 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate {
ASSERT(constSize == 16);
pushByteCode(Walrus::Const128(constPos, constantBuffer), WASMOpcode::V128ConstOpcode);
}

m_initialFunctionStackSize += Walrus::valueStackAllocatedSize(constType);
#if !defined(NDEBUG)
m_currentFunction->m_constantDebugData.pushBack(m_preprocessData.m_constantData[i].first);
m_currentFunction->m_constantDebugData.pushBack(m_preprocessData.m_constantData[i]);
#endif
}

m_functionStackSizeSoFar = m_initialFunctionStackSize;
m_currentFunction->m_requiredStackSize = m_functionStackSizeSoFar;
}

virtual void OnOpcode(uint32_t opcode) override
Expand Down Expand Up @@ -1136,13 +1191,11 @@ class WASMBinaryReader : public wabt::WASMBinaryReaderDelegate {
if (!m_inInitExpr) {
m_preprocessData.addConstantData(value);
if (!m_preprocessData.m_inPreprocess) {
size_t pos = m_currentFunction->m_requiredStackSizeDueToParameterAndLocal;
for (size_t i = 0; i < m_preprocessData.m_constantData.size(); i++) {
if (m_preprocessData.m_constantData[i].first == value) {
pushVMStack(value.type(), pos);
pushVMStack(value.type(), m_preprocessData.m_constantData[i].second);
return true;
}
pos += Walrus::valueStackAllocatedSize(m_preprocessData.m_constantData[i].first.type());
}
}
}
Expand Down
17 changes: 7 additions & 10 deletions src/runtime/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ namespace Walrus {
ModuleFunction::ModuleFunction(FunctionType* functionType)
: m_functionType(functionType)
, m_requiredStackSize(std::max(m_functionType->paramStackSize(), m_functionType->resultStackSize()))
, m_requiredStackSizeDueToParameterAndLocal(0)
{
}

Expand Down Expand Up @@ -420,24 +419,22 @@ void ModuleFunction::dumpByteCode()
{
printf("\n");
printf("required stack size: %u bytes\n", m_requiredStackSize);
printf("required stack size due to parameter and local: %u bytes\n", m_requiredStackSizeDueToParameterAndLocal);
printf("stack: [");
size_t pos = 0;
for (size_t i = 0; i < m_functionType->param().size(); i++) {
printf("%zu(parameter %zu, %s) ", pos, i, typeName(m_functionType->param()[i]));
printf("(parameter %zu, %s, pos %zu) ", i, typeName(m_functionType->param()[i]), pos);
pos += valueStackAllocatedSize(m_functionType->param()[i]);
}
for (size_t i = 0; i < m_local.size(); i++) {
printf("%zu(local %zu, %s) ", pos, i, typeName(m_local[i]));
pos += valueStackAllocatedSize(m_local[i]);
printf("(local %zu, %s, pos %zu) ", i, typeName(m_local[i]), m_localDebugData[i]);
}
for (size_t i = 0; i < m_constantDebugData.size(); i++) {
printf("%zu(constant ", pos);
dumpValue(m_constantDebugData[i]);
printf(") ");
pos += valueStackAllocatedSize(m_constantDebugData[i].type());
printf("(constant ");
dumpValue(m_constantDebugData[i].first);
printf(", pos %zu) ", m_constantDebugData[i].second);
}
printf("%zu(%" PRIu32 " bytes for general operation)]\n", pos, (m_requiredStackSize - m_requiredStackSizeDueToParameterAndLocal));
printf("....]\n");

printf("bytecode size: %zu bytes\n", m_byteCode.size());
printf("\n");

Expand Down
6 changes: 2 additions & 4 deletions src/runtime/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ class ModuleFunction {

FunctionType* functionType() const { return m_functionType; }
uint32_t requiredStackSize() const { return m_requiredStackSize; }
uint32_t requiredStackSizeDueToParameterAndLocal() const { return m_requiredStackSizeDueToParameterAndLocal; }

template <typename CodeType>
void pushByteCode(const CodeType& code)
Expand Down Expand Up @@ -220,13 +219,12 @@ class ModuleFunction {

private:
FunctionType* m_functionType;
// m_requiredStackSize = m_requiredStackSizeDueToParameterAndLocal + constant space + general purpose space
uint32_t m_requiredStackSize;
uint32_t m_requiredStackSizeDueToParameterAndLocal;
ValueTypeVector m_local;
Vector<uint8_t, std::allocator<uint8_t>> m_byteCode;
#if !defined(NDEBUG)
Vector<Value, std::allocator<Value>> m_constantDebugData;
Vector<size_t, std::allocator<size_t>> m_localDebugData;
Vector<std::pair<Value, size_t>, std::allocator<std::pair<Value, size_t>>> m_constantDebugData;
#endif
Vector<CatchInfo, std::allocator<CatchInfo>> m_catchInfo;
};
Expand Down
24 changes: 24 additions & 0 deletions src/runtime/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,30 @@ inline size_t valueFunctionCopyCount(Value::Type type)
return s;
}

inline bool hasCPUWordAlingedSize(Value::Type type)
{
#if defined(WALRUS_32)
ASSERT(valueStackAllocatedSize(type) == valueSize(type));
#endif
return valueStackAllocatedSize(type) == valueSize(type);
}

inline bool needsCPUWordAlingedAddress(Value::Type type)
{
#if defined(WALRUS_32)
// everything is already aligned!
return false;
#else
switch (type) {
case Value::FuncRef:
case Value::ExternRef:
return true;
default:
return false;
}
#endif
}

template <const size_t size>
inline void Value::readFromStack(uint8_t* ptr)
{
Expand Down

0 comments on commit b41b602

Please sign in to comment.