|
|
@@ -154,12 +154,38 @@ get_target_block(AOTFuncContext *func_ctx, uint32 br_depth)
|
|
|
return block;
|
|
|
}
|
|
|
|
|
|
+static void
|
|
|
+clear_frame_locals(AOTCompFrame *aot_frame)
|
|
|
+{
|
|
|
+ uint32 i;
|
|
|
+
|
|
|
+ for (i = 0; i < aot_frame->max_local_cell_num; i++) {
|
|
|
+ aot_frame->lp[i].dirty = 0;
|
|
|
+ aot_frame->lp[i].value = NULL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+restore_frame_sp(AOTBlock *block, AOTCompFrame *aot_frame)
|
|
|
+{
|
|
|
+ uint32 stack_cell_num;
|
|
|
+
|
|
|
+ bh_assert(aot_frame->sp >= block->frame_sp_begin);
|
|
|
+
|
|
|
+ stack_cell_num = aot_frame->sp - block->frame_sp_begin;
|
|
|
+ if (stack_cell_num > 0) {
|
|
|
+ memset(block->frame_sp_begin, 0, sizeof(AOTValueSlot) * stack_cell_num);
|
|
|
+ }
|
|
|
+ aot_frame->sp = block->frame_sp_begin;
|
|
|
+}
|
|
|
+
|
|
|
static bool
|
|
|
handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
uint8 **p_frame_ip)
|
|
|
{
|
|
|
AOTBlock *block = func_ctx->block_stack.block_list_end;
|
|
|
AOTBlock *block_prev;
|
|
|
+ AOTCompFrame *aot_frame = comp_ctx->aot_frame;
|
|
|
uint8 *frame_ip = NULL;
|
|
|
uint32 i;
|
|
|
AOTFuncType *func_type;
|
|
|
@@ -176,10 +202,22 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
comp_ctx, func_ctx,
|
|
|
(*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
|
|
|
#endif
|
|
|
+
|
|
|
+ if (aot_frame) {
|
|
|
+ /* Clear frame local variables since they have been committed */
|
|
|
+ clear_frame_locals(aot_frame);
|
|
|
+ }
|
|
|
+
|
|
|
if (block->label_type == LABEL_TYPE_IF && block->llvm_else_block
|
|
|
&& *p_frame_ip <= block->wasm_code_else) {
|
|
|
/* Clear value stack and start to translate else branch */
|
|
|
- aot_value_stack_destroy(&block->value_stack);
|
|
|
+ aot_value_stack_destroy(comp_ctx, &block->value_stack);
|
|
|
+
|
|
|
+ if (aot_frame) {
|
|
|
+ /* Restore the frame sp */
|
|
|
+ restore_frame_sp(block, aot_frame);
|
|
|
+ }
|
|
|
+
|
|
|
/* Recover parameters of else branch */
|
|
|
for (i = 0; i < block->param_count; i++)
|
|
|
PUSH(block->else_param_phis[i], block->param_types[i]);
|
|
|
@@ -192,11 +230,16 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
block_prev = block->prev;
|
|
|
block = aot_block_stack_pop(&func_ctx->block_stack);
|
|
|
|
|
|
+ if (aot_frame) {
|
|
|
+ /* Restore the frame sp */
|
|
|
+ restore_frame_sp(block, aot_frame);
|
|
|
+ }
|
|
|
+
|
|
|
if (block->label_type == LABEL_TYPE_IF) {
|
|
|
if (block->llvm_else_block && !block->skip_wasm_code_else
|
|
|
&& *p_frame_ip <= block->wasm_code_else) {
|
|
|
/* Clear value stack and start to translate else branch */
|
|
|
- aot_value_stack_destroy(&block->value_stack);
|
|
|
+ aot_value_stack_destroy(comp_ctx, &block->value_stack);
|
|
|
SET_BUILDER_POS(block->llvm_else_block);
|
|
|
*p_frame_ip = block->wasm_code_else + 1;
|
|
|
/* Push back the block */
|
|
|
@@ -211,7 +254,7 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
}
|
|
|
|
|
|
frame_ip = block->wasm_code_end;
|
|
|
- aot_block_destroy(block);
|
|
|
+ aot_block_destroy(comp_ctx, block);
|
|
|
block = block_prev;
|
|
|
}
|
|
|
|
|
|
@@ -225,6 +268,12 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
|
|
|
/* Pop block, push its return value, and destroy the block */
|
|
|
block = aot_block_stack_pop(&func_ctx->block_stack);
|
|
|
+
|
|
|
+ if (aot_frame) {
|
|
|
+ /* Restore the frame sp */
|
|
|
+ restore_frame_sp(block, aot_frame);
|
|
|
+ }
|
|
|
+
|
|
|
func_type = func_ctx->aot_func->func_type;
|
|
|
for (i = 0; i < block->result_count; i++) {
|
|
|
bh_assert(block->result_phis[i]);
|
|
|
@@ -266,7 +315,7 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
#endif
|
|
|
}
|
|
|
}
|
|
|
- aot_block_destroy(block);
|
|
|
+ aot_block_destroy(comp_ctx, block);
|
|
|
return true;
|
|
|
fail:
|
|
|
return false;
|
|
|
@@ -353,6 +402,9 @@ push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx,
|
|
|
|
|
|
/* Push the new block to block stack */
|
|
|
aot_block_stack_push(&func_ctx->block_stack, block);
|
|
|
+ if (comp_ctx->aot_frame) {
|
|
|
+ block->frame_sp_begin = comp_ctx->aot_frame->sp;
|
|
|
+ }
|
|
|
|
|
|
/* Push param phis to the new block */
|
|
|
for (i = 0; i < block->param_count; i++) {
|
|
|
@@ -435,6 +487,13 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
block->block_index = func_ctx->block_stack.block_index[label_type];
|
|
|
func_ctx->block_stack.block_index[label_type]++;
|
|
|
|
|
|
+ if (comp_ctx->aot_frame) {
|
|
|
+ if (label_type != LABEL_TYPE_BLOCK
|
|
|
+ && !aot_gen_commit_values(comp_ctx->aot_frame)) {
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (label_type == LABEL_TYPE_BLOCK || label_type == LABEL_TYPE_LOOP) {
|
|
|
/* Create block */
|
|
|
format_block_name(name, sizeof(name), block->block_index, label_type,
|
|
|
@@ -462,7 +521,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
false, NULL, NULL))) {
|
|
|
goto fail;
|
|
|
}
|
|
|
- aot_block_destroy(block);
|
|
|
+ aot_block_destroy(comp_ctx, block);
|
|
|
return aot_handle_next_reachable_block(comp_ctx, func_ctx,
|
|
|
p_frame_ip);
|
|
|
}
|
|
|
@@ -542,7 +601,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
}
|
|
|
else {
|
|
|
/* skip the block */
|
|
|
- aot_block_destroy(block);
|
|
|
+ aot_block_destroy(comp_ctx, block);
|
|
|
*p_frame_ip = end_addr + 1;
|
|
|
}
|
|
|
}
|
|
|
@@ -555,7 +614,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
|
|
|
return true;
|
|
|
fail:
|
|
|
- aot_block_destroy(block);
|
|
|
+ aot_block_destroy(comp_ctx, block);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -565,6 +624,7 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
{
|
|
|
AOTBlock *block = func_ctx->block_stack.block_list_end;
|
|
|
LLVMValueRef value;
|
|
|
+ AOTCompFrame *aot_frame = comp_ctx->aot_frame;
|
|
|
char name[32];
|
|
|
uint32 i, result_index;
|
|
|
|
|
|
@@ -600,14 +660,27 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
ADD_TO_RESULT_PHIS(block, value, result_index);
|
|
|
}
|
|
|
|
|
|
+ if (aot_frame) {
|
|
|
+ bh_assert(block->frame_sp_begin == aot_frame->sp);
|
|
|
+ aot_gen_commit_values(aot_frame);
|
|
|
+ }
|
|
|
+
|
|
|
/* Jump to end block */
|
|
|
BUILD_BR(block->llvm_end_block);
|
|
|
|
|
|
if (!block->skip_wasm_code_else && block->llvm_else_block) {
|
|
|
/* Clear value stack, recover param values
|
|
|
- * and start to translate else branch.
|
|
|
- */
|
|
|
- aot_value_stack_destroy(&block->value_stack);
|
|
|
+ and start to translate else branch. */
|
|
|
+ aot_value_stack_destroy(comp_ctx, &block->value_stack);
|
|
|
+
|
|
|
+ if (comp_ctx->aot_frame) {
|
|
|
+ comp_ctx->aot_frame->sp = block->frame_sp_begin;
|
|
|
+ for (i = 0; i < comp_ctx->aot_frame->max_local_cell_num; i++) {
|
|
|
+ comp_ctx->aot_frame->lp[i].dirty = 0;
|
|
|
+ comp_ctx->aot_frame->lp[i].value = NULL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
for (i = 0; i < block->param_count; i++)
|
|
|
PUSH(block->else_param_phis[i], block->param_types[i]);
|
|
|
SET_BUILDER_POS(block->llvm_else_block);
|
|
|
@@ -647,6 +720,13 @@ aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block);
|
|
|
}
|
|
|
|
|
|
+ if (comp_ctx->aot_frame) {
|
|
|
+ if (block->label_type != LABEL_TYPE_FUNCTION
|
|
|
+ && !aot_gen_commit_values(comp_ctx->aot_frame)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/* Handle block result values */
|
|
|
CREATE_RESULT_VALUE_PHIS(block);
|
|
|
for (i = 0; i < block->result_count; i++) {
|
|
|
@@ -657,6 +737,10 @@ aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
ADD_TO_RESULT_PHIS(block, value, result_index);
|
|
|
}
|
|
|
|
|
|
+ if (comp_ctx->aot_frame) {
|
|
|
+ restore_frame_sp(block, comp_ctx->aot_frame);
|
|
|
+ }
|
|
|
+
|
|
|
/* Jump to the end block */
|
|
|
BUILD_BR(block->llvm_end_block);
|
|
|
|
|
|
@@ -668,7 +752,8 @@ fail:
|
|
|
|
|
|
#if WASM_ENABLE_THREAD_MGR != 0
|
|
|
bool
|
|
|
-check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
|
|
|
+check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
+ bool check_terminate_and_suspend)
|
|
|
{
|
|
|
LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
|
|
|
LLVMBasicBlockRef terminate_block, non_terminate_block;
|
|
|
@@ -748,17 +833,28 @@ aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
char name[32];
|
|
|
uint32 i, param_index, result_index;
|
|
|
|
|
|
-#if WASM_ENABLE_THREAD_MGR != 0
|
|
|
- /* Insert suspend check point */
|
|
|
- if (comp_ctx->enable_thread_mgr) {
|
|
|
- if (!check_suspend_flags(comp_ctx, func_ctx))
|
|
|
+ if (!(block_dst = get_target_block(func_ctx, br_depth))) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (comp_ctx->aot_frame) {
|
|
|
+ if (!aot_gen_commit_values(comp_ctx->aot_frame))
|
|
|
return false;
|
|
|
+ if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
|
|
+ if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
|
|
|
+ comp_ctx->aot_frame->sp, *p_frame_ip))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
- if (!(block_dst = get_target_block(func_ctx, br_depth))) {
|
|
|
- return false;
|
|
|
+#if WASM_ENABLE_THREAD_MGR != 0
|
|
|
+ /* Terminate or suspend current thread only when this is a backward jump */
|
|
|
+ if (comp_ctx->enable_thread_mgr
|
|
|
+ && block_dst->label_type == LABEL_TYPE_LOOP) {
|
|
|
+ if (!check_suspend_flags(comp_ctx, func_ctx, true))
|
|
|
+ return false;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
|
|
/* Dest block is Loop block */
|
|
|
@@ -811,13 +907,19 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
uint32 i, param_index, result_index;
|
|
|
uint64 size;
|
|
|
|
|
|
-#if WASM_ENABLE_THREAD_MGR != 0
|
|
|
- /* Insert suspend check point */
|
|
|
- if (comp_ctx->enable_thread_mgr) {
|
|
|
- if (!check_suspend_flags(comp_ctx, func_ctx))
|
|
|
+ if (!(block_dst = get_target_block(func_ctx, br_depth))) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (comp_ctx->aot_frame) {
|
|
|
+ if (!aot_gen_commit_values(comp_ctx->aot_frame))
|
|
|
return false;
|
|
|
+ if (block_dst->label_type == LABEL_TYPE_LOOP) {
|
|
|
+ if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame,
|
|
|
+ comp_ctx->aot_frame->sp, *p_frame_ip))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
POP_COND(value_cmp);
|
|
|
|
|
|
@@ -839,6 +941,16 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+#if WASM_ENABLE_THREAD_MGR != 0
|
|
|
+ /* Terminate or suspend current thread only when this is
|
|
|
+ a backward jump */
|
|
|
+ if (comp_ctx->enable_thread_mgr
|
|
|
+ && block_dst->label_type == LABEL_TYPE_LOOP) {
|
|
|
+ if (!check_suspend_flags(comp_ctx, func_ctx, true))
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
/* Create llvm else block */
|
|
|
CREATE_BLOCK(llvm_else_block, "br_if_else");
|
|
|
MOVE_BLOCK_AFTER_CURR(llvm_else_block);
|
|
|
@@ -948,13 +1060,13 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
uint64 size;
|
|
|
char name[32];
|
|
|
|
|
|
-#if WASM_ENABLE_THREAD_MGR != 0
|
|
|
- /* Insert suspend check point */
|
|
|
- if (comp_ctx->enable_thread_mgr) {
|
|
|
- if (!check_suspend_flags(comp_ctx, func_ctx))
|
|
|
+ if (comp_ctx->aot_frame) {
|
|
|
+ if (!aot_gen_commit_values(comp_ctx->aot_frame))
|
|
|
+ return false;
|
|
|
+ if (!aot_gen_commit_sp_ip(comp_ctx->aot_frame, comp_ctx->aot_frame->sp,
|
|
|
+ *p_frame_ip))
|
|
|
return false;
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
POP_I32(value_cmp);
|
|
|
|
|
|
@@ -971,6 +1083,23 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
}
|
|
|
|
|
|
if (!LLVMIsConstant(value_cmp)) {
|
|
|
+#if WASM_ENABLE_THREAD_MGR != 0
|
|
|
+ if (comp_ctx->enable_thread_mgr) {
|
|
|
+ for (i = 0; i <= br_count; i++) {
|
|
|
+ target_block = get_target_block(func_ctx, br_depths[i]);
|
|
|
+ if (!target_block)
|
|
|
+ return false;
|
|
|
+ /* Terminate or suspend current thread only when this is a
|
|
|
+ backward jump */
|
|
|
+ if (target_block->label_type == LABEL_TYPE_LOOP) {
|
|
|
+ if (!check_suspend_flags(comp_ctx, func_ctx, true))
|
|
|
+ return false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
/* Compare value is not constant, create switch IR */
|
|
|
for (i = 0; i <= br_count; i++) {
|
|
|
target_block = get_target_block(func_ctx, br_depths[i]);
|
|
|
@@ -1099,6 +1228,7 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
|
|
|
comp_ctx, func_ctx,
|
|
|
(*p_frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
|
|
|
#endif
|
|
|
+
|
|
|
if (block_func->result_count) {
|
|
|
/* Store extra result values to function parameters */
|
|
|
for (i = 0; i < block_func->result_count - 1; i++) {
|