Skip to content

Commit 6e4b2db

Browse files
authored
Implement bulk memory opcodes (#1245)
1 parent 8ee2e0a commit 6e4b2db

File tree

3 files changed

+202
-21
lines changed

3 files changed

+202
-21
lines changed

core/iwasm/fast-jit/fe/jit_emit_memory.c

Lines changed: 183 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ jit_compile_op_memory_grow(JitCompContext *cc, uint32 mem_idx)
510510
/* Convert bool to uint32 */
511511
GEN_INSN(AND, grow_res, grow_res, NEW_CONST(I32, 0xFF));
512512

513-
/* Check if enlarge memory success */
513+
/* return different values according to memory.grow result */
514514
res = jit_cc_new_reg_I32(cc);
515515
GEN_INSN(CMP, cc->cmp_reg, grow_res, NEW_CONST(I32, 0));
516516
GEN_INSN(SELECTNE, res, cc->cmp_reg, prev_page_count,
@@ -526,27 +526,204 @@ jit_compile_op_memory_grow(JitCompContext *cc, uint32 mem_idx)
526526
}
527527

528528
#if WASM_ENABLE_BULK_MEMORY != 0
529+
static int
530+
wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx,
531+
uint32 len, uint32 mem_offset, uint32 data_offset)
532+
{
533+
WASMMemoryInstance *mem_inst;
534+
WASMDataSeg *data_segment;
535+
uint32 mem_size;
536+
uint8 *mem_addr, *data_addr;
537+
538+
/* if d + n > the length of mem.data */
539+
mem_inst = inst->memories[mem_idx];
540+
mem_size = mem_inst->cur_page_count * mem_inst->num_bytes_per_page;
541+
if (mem_size < mem_offset || mem_size - mem_offset < len)
542+
goto out_of_bounds;
543+
544+
/* if s + n > the length of data.data */
545+
bh_assert(seg_idx < inst->module->data_seg_count);
546+
data_segment = inst->module->data_segments[seg_idx];
547+
if (data_segment->data_length < data_offset
548+
|| data_segment->data_length - data_offset < len)
549+
goto out_of_bounds;
550+
551+
mem_addr = mem_inst->memory_data + mem_offset;
552+
data_addr = data_segment->data + data_offset;
553+
bh_memcpy_s(mem_addr, mem_size - mem_offset, data_addr, len);
554+
555+
return 0;
556+
out_of_bounds:
557+
wasm_set_exception(inst, "out of bounds memory access");
558+
return -1;
559+
}
560+
529561
bool
530-
jit_compile_op_memory_init(JitCompContext *cc, uint32 seg_index)
562+
jit_compile_op_memory_init(JitCompContext *cc, uint32 mem_idx, uint32 seg_idx)
531563
{
564+
JitReg len, mem_offset, data_offset, res;
565+
JitReg args[6] = { 0 };
566+
567+
POP_I32(len);
568+
POP_I32(data_offset);
569+
POP_I32(mem_offset);
570+
571+
res = jit_cc_new_reg_I32(cc);
572+
args[0] = get_module_inst_reg(cc->jit_frame);
573+
args[1] = NEW_CONST(I32, mem_idx);
574+
args[2] = NEW_CONST(I32, seg_idx);
575+
args[3] = len;
576+
args[4] = mem_offset;
577+
args[5] = data_offset;
578+
579+
if (!jit_emit_callnative(cc, wasm_init_memory, res, args,
580+
sizeof(args) / sizeof(args[0])))
581+
goto fail;
582+
583+
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
584+
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
585+
NULL))
586+
goto fail;
587+
588+
return true;
589+
fail:
532590
return false;
533591
}
534592

535593
bool
536-
jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_index)
594+
jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_idx)
537595
{
538-
return false;
596+
JitReg module = get_module_reg(cc->jit_frame);
597+
JitReg data_segments = jit_cc_new_reg_ptr(cc);
598+
JitReg data_segment = jit_cc_new_reg_ptr(cc);
599+
600+
GEN_INSN(LDPTR, data_segments, module,
601+
NEW_CONST(I32, offsetof(WASMModule, data_segments)));
602+
GEN_INSN(LDPTR, data_segment, data_segments,
603+
NEW_CONST(I32, seg_idx * sizeof(WASMDataSeg *)));
604+
GEN_INSN(STI32, NEW_CONST(I32, 0), data_segment,
605+
NEW_CONST(I32, offsetof(WASMDataSeg, data_length)));
606+
607+
return true;
608+
}
609+
610+
static int
611+
wasm_copy_memory(WASMModuleInstance *inst, uint32 src_mem_idx,
612+
uint32 dst_mem_idx, uint32 len, uint32 src_offset,
613+
uint32 dst_offset)
614+
{
615+
WASMMemoryInstance *src_mem, *dst_mem;
616+
uint32 src_mem_size, dst_mem_size;
617+
uint8 *src_addr, *dst_addr;
618+
619+
src_mem = inst->memories[src_mem_idx];
620+
dst_mem = inst->memories[dst_mem_idx];
621+
src_mem_size = src_mem->cur_page_count * src_mem->num_bytes_per_page;
622+
dst_mem_size = dst_mem->cur_page_count * dst_mem->num_bytes_per_page;
623+
624+
/* if s + n > the length of mem.data */
625+
if (src_mem_size < src_offset || src_mem_size - src_offset < len)
626+
goto out_of_bounds;
627+
628+
/* if d + n > the length of mem.data */
629+
if (dst_mem_size < dst_offset || dst_mem_size - dst_offset < len)
630+
goto out_of_bounds;
631+
632+
src_addr = src_mem->memory_data + src_offset;
633+
dst_addr = dst_mem->memory_data + dst_offset;
634+
/* allowing the destination and source to overlap */
635+
bh_memmove_s(dst_addr, dst_mem_size - dst_offset, src_addr, len);
636+
637+
return 0;
638+
out_of_bounds:
639+
wasm_set_exception(inst, "out of bounds memory access");
640+
return -1;
539641
}
540642

541643
bool
542-
jit_compile_op_memory_copy(JitCompContext *cc)
644+
jit_compile_op_memory_copy(JitCompContext *cc, uint32 src_mem_idx,
645+
uint32 dst_mem_idx)
543646
{
647+
JitReg len, src, dst, res;
648+
JitReg args[6] = { 0 };
649+
650+
POP_I32(len);
651+
POP_I32(src);
652+
POP_I32(dst);
653+
654+
res = jit_cc_new_reg_I32(cc);
655+
args[0] = get_module_inst_reg(cc->jit_frame);
656+
args[1] = NEW_CONST(I32, src_mem_idx);
657+
args[2] = NEW_CONST(I32, dst_mem_idx);
658+
args[3] = len;
659+
args[4] = src;
660+
args[5] = dst;
661+
662+
if (!jit_emit_callnative(cc, wasm_copy_memory, res, args,
663+
sizeof(args) / sizeof(args[0])))
664+
goto fail;
665+
666+
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
667+
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
668+
NULL))
669+
goto fail;
670+
671+
return true;
672+
fail:
544673
return false;
545674
}
546675

676+
static int
677+
wasm_fill_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 len,
678+
uint32 val, uint32 dst)
679+
{
680+
WASMMemoryInstance *mem_inst;
681+
uint32 mem_size;
682+
uint8 *dst_addr;
683+
684+
mem_inst = inst->memories[mem_idx];
685+
mem_size = mem_inst->cur_page_count * mem_inst->num_bytes_per_page;
686+
687+
if (mem_size < dst || mem_size - dst < len)
688+
goto out_of_bounds;
689+
690+
dst_addr = mem_inst->memory_data + dst;
691+
memset(dst_addr, val, len);
692+
693+
return 0;
694+
out_of_bounds:
695+
wasm_set_exception(inst, "out of bounds memory access");
696+
return -1;
697+
}
698+
547699
bool
548-
jit_compile_op_memory_fill(JitCompContext *cc)
700+
jit_compile_op_memory_fill(JitCompContext *cc, uint32 mem_idx)
549701
{
702+
JitReg res, len, val, dst;
703+
JitReg args[5] = { 0 };
704+
705+
POP_I32(len);
706+
POP_I32(val);
707+
POP_I32(dst);
708+
709+
res = jit_cc_new_reg_I32(cc);
710+
args[0] = get_module_inst_reg(cc->jit_frame);
711+
args[1] = NEW_CONST(I32, mem_idx);
712+
args[2] = len;
713+
args[3] = val;
714+
args[4] = dst;
715+
716+
if (!jit_emit_callnative(cc, wasm_fill_memory, res, args,
717+
sizeof(args) / sizeof(args[0])))
718+
goto fail;
719+
720+
GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
721+
if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
722+
NULL))
723+
goto fail;
724+
725+
return true;
726+
fail:
550727
return false;
551728
}
552729
#endif

core/iwasm/fast-jit/fe/jit_emit_memory.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,17 @@ jit_compile_op_memory_grow(JitCompContext *cc, uint32 mem_idx);
5151

5252
#if WASM_ENABLE_BULK_MEMORY != 0
5353
bool
54-
jit_compile_op_memory_init(JitCompContext *cc, uint32 seg_index);
54+
jit_compile_op_memory_init(JitCompContext *cc, uint32 mem_idx, uint32 seg_idx);
5555

5656
bool
57-
jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_index);
57+
jit_compile_op_data_drop(JitCompContext *cc, uint32 seg_idx);
5858

5959
bool
60-
jit_compile_op_memory_copy(JitCompContext *cc);
60+
jit_compile_op_memory_copy(JitCompContext *cc, uint32 src_mem_idx,
61+
uint32 dst_mem_idx);
6162

6263
bool
63-
jit_compile_op_memory_fill(JitCompContext *cc);
64+
jit_compile_op_memory_fill(JitCompContext *cc, uint32 mem_idx);
6465
#endif
6566

6667
#if WASM_ENABLE_SHARED_MEMORY != 0

core/iwasm/fast-jit/jit_frontend.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,32 +1823,35 @@ jit_compile_func(JitCompContext *cc)
18231823
#if WASM_ENABLE_BULK_MEMORY != 0
18241824
case WASM_OP_MEMORY_INIT:
18251825
{
1826-
uint32 seg_index;
1827-
read_leb_uint32(frame_ip, frame_ip_end, seg_index);
1828-
frame_ip++;
1829-
if (!jit_compile_op_memory_init(cc, seg_index))
1826+
uint32 seg_idx = 0;
1827+
read_leb_uint32(frame_ip, frame_ip_end, seg_idx);
1828+
read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
1829+
if (!jit_compile_op_memory_init(cc, mem_idx, seg_idx))
18301830
return false;
18311831
break;
18321832
}
18331833
case WASM_OP_DATA_DROP:
18341834
{
1835-
uint32 seg_index;
1836-
read_leb_uint32(frame_ip, frame_ip_end, seg_index);
1837-
if (!jit_compile_op_data_drop(cc, seg_index))
1835+
uint32 seg_idx;
1836+
read_leb_uint32(frame_ip, frame_ip_end, seg_idx);
1837+
if (!jit_compile_op_data_drop(cc, seg_idx))
18381838
return false;
18391839
break;
18401840
}
18411841
case WASM_OP_MEMORY_COPY:
18421842
{
1843-
frame_ip += 2;
1844-
if (!jit_compile_op_memory_copy(cc))
1843+
uint32 src_mem_idx, dst_mem_idx;
1844+
read_leb_uint32(frame_ip, frame_ip_end, src_mem_idx);
1845+
read_leb_uint32(frame_ip, frame_ip_end, dst_mem_idx);
1846+
if (!jit_compile_op_memory_copy(cc, src_mem_idx,
1847+
dst_mem_idx))
18451848
return false;
18461849
break;
18471850
}
18481851
case WASM_OP_MEMORY_FILL:
18491852
{
1850-
frame_ip++;
1851-
if (!jit_compile_op_memory_fill(cc))
1853+
read_leb_uint32(frame_ip, frame_ip_end, mem_idx);
1854+
if (!jit_compile_op_memory_fill(cc, mem_idx))
18521855
return false;
18531856
break;
18541857
}

0 commit comments

Comments
 (0)