Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
344 changes: 278 additions & 66 deletions src/interpreter/ByteCode.h

Large diffs are not rendered by default.

120 changes: 107 additions & 13 deletions src/interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2190,67 +2190,161 @@ ByteCodeStackOffset* Interpreter::interpret(ExecutionState& state,
:
{
MemorySize* code = (MemorySize*)programCounter;
writeValue<int32_t>(bp, code->dstOffset(), memories[code->memIndex()]->sizeInPageSize());
writeValue<uint32_t>(bp, code->dstOffset(), memories[code->memIndex()]->sizeInPageSize());
ADD_PROGRAM_COUNTER(MemorySize);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemorySizeM64)
:
{
MemorySizeM64* code = (MemorySizeM64*)programCounter;
writeValue<uint64_t>(bp, code->dstOffset(), memories[code->memIndex()]->sizeInPageSize());
ADD_PROGRAM_COUNTER(MemorySizeM64);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryGrow)
:
{
MemoryGrow* code = (MemoryGrow*)programCounter;
Memory* m = memories[code->memIndex()];
auto oldSize = m->sizeInPageSize();
if (m->grow(readValue<int32_t>(bp, code->srcOffset()) * (uint64_t)Memory::s_memoryPageSize)) {
writeValue<int32_t>(bp, code->dstOffset(), oldSize);
if (m->grow(readValue<uint32_t>(bp, code->srcOffset()) * (uint64_t)Memory::s_memoryPageSize)) {
writeValue<uint32_t>(bp, code->dstOffset(), oldSize);
} else {
writeValue<int32_t>(bp, code->dstOffset(), -1);
writeValue<uint32_t>(bp, code->dstOffset(), -1);
}
ADD_PROGRAM_COUNTER(MemoryGrow);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryGrowM64)
:
{
MemoryGrowM64* code = (MemoryGrowM64*)programCounter;
Memory* m = memories[code->memIndex()];
auto oldSize = m->sizeInPageSize();
uint64_t value = readValue<uint64_t>(bp, code->srcOffset());
if (value < Memory::s_maxMemory64Grow && m->grow(value * (uint64_t)Memory::s_memoryPageSize)) {
writeValue<uint64_t>(bp, code->dstOffset(), oldSize);
} else {
writeValue<uint64_t>(bp, code->dstOffset(), -1);
}
ADD_PROGRAM_COUNTER(MemoryGrowM64);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryInit)
:
{
MemoryInit* code = (MemoryInit*)programCounter;
Memory* m = memories[code->memIndex()];
DataSegment* sg = instance->dataSegment(code->segmentIndex());
auto dstStart = readValue<int32_t>(bp, code->srcOffsets()[0]);
auto srcStart = readValue<int32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<int32_t>(bp, code->srcOffsets()[2]);
auto dstStart = readValue<uint32_t>(bp, code->srcOffsets()[0]);
auto srcStart = readValue<uint32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<uint32_t>(bp, code->srcOffsets()[2]);
m->init(state, sg, dstStart, srcStart, size);
ADD_PROGRAM_COUNTER(MemoryInit);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryInitM64)
:
{
MemoryInitM64* code = (MemoryInitM64*)programCounter;
Memory* m = memories[code->memIndex()];
DataSegment* sg = instance->dataSegment(code->segmentIndex());
auto dstStart = readValue<uint64_t>(bp, code->srcOffsets()[0]);
auto srcStart = readValue<uint32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<uint32_t>(bp, code->srcOffsets()[2]);
m->init(state, sg, dstStart, srcStart, size);
ADD_PROGRAM_COUNTER(MemoryInitM64);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryCopy)
:
{
MemoryCopy* code = (MemoryCopy*)programCounter;
Memory* srcMem = memories[code->srcMemIndex()];
Memory* dstMem = memories[code->dstMemIndex()];
auto dstStart = readValue<int32_t>(bp, code->srcOffsets()[0]);
auto srcStart = readValue<int32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<int32_t>(bp, code->srcOffsets()[2]);
auto dstStart = readValue<uint32_t>(bp, code->srcOffsets()[0]);
auto srcStart = readValue<uint32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<uint32_t>(bp, code->srcOffsets()[2]);
srcMem->copy(state, dstStart, srcStart, size, dstMem);
ADD_PROGRAM_COUNTER(MemoryCopy);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryCopyM64)
:
{
MemoryCopyM64* code = (MemoryCopyM64*)programCounter;
Memory* srcMem = memories[code->srcMemIndex()];
Memory* dstMem = memories[code->dstMemIndex()];
auto dstStart = readValue<uint64_t>(bp, code->srcOffsets()[0]);
auto srcStart = readValue<uint64_t>(bp, code->srcOffsets()[1]);
auto size = readValue<uint64_t>(bp, code->srcOffsets()[2]);
srcMem->copy(state, dstStart, srcStart, size, dstMem);
ADD_PROGRAM_COUNTER(MemoryCopyM64);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryCopyM64M32)
:
{
MemoryCopyM64M32* code = (MemoryCopyM64M32*)programCounter;
Memory* srcMem = memories[code->srcMemIndex()];
Memory* dstMem = memories[code->dstMemIndex()];
auto dstStart = readValue<uint64_t>(bp, code->srcOffsets()[0]);
auto srcStart = readValue<uint32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<uint32_t>(bp, code->srcOffsets()[2]);
srcMem->copy(state, dstStart, srcStart, size, dstMem);
ADD_PROGRAM_COUNTER(MemoryCopyM64M32);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryCopyM32M64)
:
{
MemoryCopyM32M64* code = (MemoryCopyM32M64*)programCounter;
Memory* srcMem = memories[code->srcMemIndex()];
Memory* dstMem = memories[code->dstMemIndex()];
auto dstStart = readValue<uint32_t>(bp, code->srcOffsets()[0]);
auto srcStart = readValue<uint64_t>(bp, code->srcOffsets()[1]);
auto size = readValue<uint32_t>(bp, code->srcOffsets()[2]);
srcMem->copy(state, dstStart, srcStart, size, dstMem);
ADD_PROGRAM_COUNTER(MemoryCopyM32M64);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryFill)
:
{
MemoryFill* code = (MemoryFill*)programCounter;
Memory* m = memories[code->memIndex()];
auto dstStart = readValue<int32_t>(bp, code->srcOffsets()[0]);
auto value = readValue<int32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<int32_t>(bp, code->srcOffsets()[2]);
auto dstStart = readValue<uint32_t>(bp, code->srcOffsets()[0]);
auto value = readValue<uint32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<uint32_t>(bp, code->srcOffsets()[2]);
m->fill(state, dstStart, value, size);
ADD_PROGRAM_COUNTER(MemoryFill);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(MemoryFillM64)
:
{
MemoryFillM64* code = (MemoryFillM64*)programCounter;
Memory* m = memories[code->memIndex()];
auto dstStart = readValue<uint64_t>(bp, code->srcOffsets()[0]);
auto value = readValue<uint32_t>(bp, code->srcOffsets()[1]);
auto size = readValue<uint64_t>(bp, code->srcOffsets()[2]);
m->fill(state, dstStart, value, size);
ADD_PROGRAM_COUNTER(MemoryFillM64);
NEXT_INSTRUCTION();
}

DEFINE_OPCODE(DataDrop)
:
{
Expand Down
9 changes: 7 additions & 2 deletions src/jit/Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,8 @@ static void emitInitR0R1(sljit_compiler* compiler, sljit_s32 movOp1, sljit_s32 m
sljit_emit_op1(compiler, movOp2, SLJIT_R1, 0, SLJIT_TMP_DEST_REG, 0);
}

static void emitInitR0R1R2(sljit_compiler* compiler, sljit_s32 movOp1, sljit_s32 movOp2, sljit_s32 movOp3, Operand* params)
static void emitInitR0R1R2Args(sljit_compiler* compiler, sljit_s32 movOp1, sljit_s32 movOp2, sljit_s32 movOp3, JITArg src[3])
{
JITArg src[3] = { params, params + 1, params + 2 };
int i = 0;

if (src[1].arg == SLJIT_R0 || src[2].arg == SLJIT_R0) {
Expand Down Expand Up @@ -379,6 +378,12 @@ static void emitInitR0R1R2(sljit_compiler* compiler, sljit_s32 movOp1, sljit_s32
}
}

static void emitInitR0R1R2(sljit_compiler* compiler, sljit_s32 movOp1, sljit_s32 movOp2, sljit_s32 movOp3, Operand* params)
{
JITArg src[3] = { params, params + 1, params + 2 };
emitInitR0R1R2Args(compiler, movOp1, movOp2, movOp3, src);
}

static void emitSelect128(sljit_compiler*, Instruction*, sljit_s32);
static void emitMove(sljit_compiler*, uint32_t type, Operand* from, Operand* to);
static void emitStoreImmediate(sljit_compiler* compiler, Operand* to, Instruction* instr, bool isFloat);
Expand Down
92 changes: 70 additions & 22 deletions src/jit/ByteCodeParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,11 @@ static bool isFloatGlobal(uint32_t globalIndex, Module* module)
OL4(OTStoreF64M64, /* SSTT */ I64, F64 | NOTMP, PTR, I32 | S0) \
OL4(OTStoreV128, /* SSTT */ I32, V128 | TMP, PTR, I32 | S0) \
OL4(OTStoreV128M64, /* SSTT */ I64, V128 | TMP, PTR, I32 | S0) \
OL3(OTCallback3Arg, /* SSS */ I32, I32, I32) \
OL3(OTCallbackI32I32I32, /* SSS */ I32, I32, I32) \
OL3(OTCallbackI64I64I64, /* SSS */ I64, I64, I64) \
OL3(OTCallbackI64I32I32, /* SSS */ I64, I32, I32) \
OL3(OTCallbackI32I64I32, /* SSS */ I32, I64, I32) \
OL3(OTCallbackI64I32I64, /* SSS */ I64, I32, I64) \
OL3(OTTableGrow, /* SSD */ PTR, I32, I32 | S0 | S1) \
OL3(OTTableFill, /* SSS */ I32, PTR, I32) \
OL4(OTTableSet, /* SSTT */ I32, PTR, I32 | S0, PTR) \
Expand Down Expand Up @@ -1812,7 +1816,7 @@ static void compileFunction(JITCompiler* compiler)

Instruction* instr = compiler->append(byteCode, Instruction::Table, opcode, 3, 0);
instr->addInfo(Instruction::kIsCallback);
instr->setRequiredRegsDescriptor(OTCallback3Arg);
instr->setRequiredRegsDescriptor(OTCallbackI32I32I32);
compiler->increaseStackTmpSize(sizeof(TableInitArguments));

Operand* operands = instr->operands();
Expand All @@ -1832,7 +1836,7 @@ static void compileFunction(JITCompiler* compiler)

Instruction* instr = compiler->append(byteCode, Instruction::Table, opcode, 3, 0);
instr->addInfo(Instruction::kIsCallback);
instr->setRequiredRegsDescriptor(OTCallback3Arg);
instr->setRequiredRegsDescriptor(OTCallbackI32I32I32);
compiler->increaseStackTmpSize(sizeof(TableCopyArguments));

Operand* operands = instr->operands();
Expand Down Expand Up @@ -1879,21 +1883,23 @@ static void compileFunction(JITCompiler* compiler)
requiredInit = OTTableGet;
break;
}
case ByteCode::MemorySizeOpcode: {
MemorySize* memorySize = reinterpret_cast<MemorySize*>(byteCode);
case ByteCode::MemorySizeOpcode:
case ByteCode::MemorySizeM64Opcode: {
ByteCodeOffsetMemIndex* memorySize = reinterpret_cast<ByteCodeOffsetMemIndex*>(byteCode);

Instruction* instr = compiler->append(byteCode, Instruction::Memory, opcode, 0, 1);
instr->setRequiredRegsDescriptor(OTPutI32);
instr->setRequiredRegsDescriptor(opcode == ByteCode::MemorySizeOpcode ? OTPutI32 : OTPutI64);

*instr->operands() = STACK_OFFSET(memorySize->dstOffset());
*instr->operands() = STACK_OFFSET(memorySize->stackOffset1());
break;
}
case ByteCode::MemoryInitOpcode: {
MemoryInit* memoryInit = reinterpret_cast<MemoryInit*>(byteCode);
case ByteCode::MemoryInitOpcode:
case ByteCode::MemoryInitM64Opcode: {
ByteCodeOffset3MemIndexSegmentIndex* memoryInit = reinterpret_cast<ByteCodeOffset3MemIndexSegmentIndex*>(byteCode);

Instruction* instr = compiler->append(byteCode, Instruction::Memory, opcode, 3, 0);
instr->addInfo(Instruction::kIsCallback);
instr->setRequiredRegsDescriptor(OTCallback3Arg);
instr->setRequiredRegsDescriptor(opcode == ByteCode::MemoryInitOpcode ? OTCallbackI32I32I32 : OTCallbackI64I32I32);
compiler->increaseStackTmpSize(sizeof(MemoryInitArguments));

Operand* operands = instr->operands();
Expand All @@ -1902,22 +1908,64 @@ static void compileFunction(JITCompiler* compiler)
operands[2] = STACK_OFFSET(memoryInit->srcOffsets()[2]);
break;
}
case ByteCode::MemoryFillOpcode:
case ByteCode::MemoryFillM64Opcode: {
ByteCodeOffset3MemIndex* memoryFill = reinterpret_cast<ByteCodeOffset3MemIndex*>(byteCode);

Instruction* instr = compiler->append(byteCode, Instruction::Memory, opcode, 3, 0);
instr->addInfo(Instruction::kIsCallback);
instr->setRequiredRegsDescriptor(opcode == ByteCode::MemoryFillOpcode ? OTCallbackI32I32I32 : OTCallbackI64I32I64);

Operand* operands = instr->operands();
operands[0] = STACK_OFFSET(memoryFill->srcOffsets()[0]);
operands[1] = STACK_OFFSET(memoryFill->srcOffsets()[1]);
operands[2] = STACK_OFFSET(memoryFill->srcOffsets()[2]);
break;
}
case ByteCode::MemoryCopyOpcode:
case ByteCode::MemoryFillOpcode: {
group = Instruction::Memory;
paramType = ParamTypes::ParamSrc3;
info = Instruction::kIsCallback;
requiredInit = OTCallback3Arg;
if (opcode == ByteCode::MemoryCopyOpcode) {
compiler->increaseStackTmpSize(sizeof(MemoryCopyArguments));
case ByteCode::MemoryCopyM64Opcode:
case ByteCode::MemoryCopyM64M32Opcode:
case ByteCode::MemoryCopyM32M64Opcode: {
ByteCodeOffset3MemIndex2* memoryCopy = reinterpret_cast<ByteCodeOffset3MemIndex2*>(byteCode);

Instruction* instr = compiler->append(byteCode, Instruction::Memory, opcode, 3, 0);
instr->addInfo(Instruction::kIsCallback);

switch (opcode) {
case ByteCode::MemoryCopyM64Opcode:
requiredInit = OTCallbackI64I64I64;
break;
case ByteCode::MemoryCopyM64M32Opcode:
requiredInit = OTCallbackI64I32I32;
break;
case ByteCode::MemoryCopyM32M64Opcode:
requiredInit = OTCallbackI32I64I32;
break;
default:
requiredInit = OTCallbackI32I32I32;
break;
}

instr->setRequiredRegsDescriptor(requiredInit);
compiler->increaseStackTmpSize(sizeof(MemoryCopyArguments));

Operand* operands = instr->operands();
operands[0] = STACK_OFFSET(memoryCopy->srcOffsets()[0]);
operands[1] = STACK_OFFSET(memoryCopy->srcOffsets()[1]);
operands[2] = STACK_OFFSET(memoryCopy->srcOffsets()[2]);
break;
}
case ByteCode::MemoryGrowOpcode: {
group = Instruction::Memory;
paramType = ParamTypes::ParamSrcDst;
info = Instruction::kIsCallback;
requiredInit = OTOp1I32;
case ByteCode::MemoryGrowOpcode:
case ByteCode::MemoryGrowM64Opcode: {
ByteCodeOffset2MemIndex* memoryGrow = reinterpret_cast<ByteCodeOffset2MemIndex*>(byteCode);

Instruction* instr = compiler->append(byteCode, Instruction::Memory, opcode, 1, 1);
instr->addInfo(Instruction::kIsCallback);
instr->setRequiredRegsDescriptor(opcode == ByteCode::MemoryGrowOpcode ? OTOp1I32 : OTOp1I64);

Operand* operands = instr->operands();
operands[0] = STACK_OFFSET(memoryGrow->stackOffset1());
operands[1] = STACK_OFFSET(memoryGrow->stackOffset2());
break;
}
case ByteCode::DataDropOpcode: {
Expand Down
Loading
Loading