@@ -5280,9 +5280,8 @@ typedef struct BranchBlock {
52805280 BranchBlockPatch * patch_list ;
52815281 /* This is used to save params frame_offset of of if block */
52825282 int16 * param_frame_offsets ;
5283- /* This is used to store available param num for if/else branch, so the else
5284- * opcode can know how many parameters should be copied to the stack */
5285- uint32 available_param_num ;
5283+ /* This is used to recover dynamic offset for else branch */
5284+ uint16 start_dynamic_offset ;
52865285#endif
52875286
52885287 /* Indicate the operand stack is in polymorphic state.
@@ -7219,18 +7218,15 @@ check_block_stack(WASMLoaderContext *loader_ctx, BranchBlock *block,
72197218 * 1) POP original parameter out;
72207219 * 2) Push and copy original values to dynamic space.
72217220 * The copy instruction format:
7222- * Part a: available param count
7221+ * Part a: param count
72237222 * Part b: all param total cell num
72247223 * Part c: each param's cell_num, src offset and dst offset
72257224 * Part d: each param's src offset
72267225 * Part e: each param's dst offset
7227- * Note: if the stack is in polymorphic state, the actual copied parameters may
7228- * be fewer than the defined number in block type
72297226 */
72307227static bool
72317228copy_params_to_dynamic_space (WASMLoaderContext * loader_ctx , bool is_if_block ,
7232- uint32 * p_available_param_count , char * error_buf ,
7233- uint32 error_buf_size )
7229+ char * error_buf , uint32 error_buf_size )
72347230{
72357231 bool ret = false;
72367232 int16 * frame_offset = NULL ;
@@ -7242,91 +7238,72 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
72427238 BlockType * block_type = & block -> block_type ;
72437239 WASMType * wasm_type = block_type -> u .type ;
72447240 uint32 param_count = block_type -> u .type -> param_count ;
7245- uint32 available_param_count = 0 ;
72467241 int16 condition_offset = 0 ;
72477242 bool disable_emit = false;
72487243 int16 operand_offset = 0 ;
7249- uint64 size ;
7250-
7251- if (is_if_block )
7252- condition_offset = * loader_ctx -> frame_offset ;
7253-
7254- /* POP original parameter out */
7255- for (i = 0 ; i < param_count ; i ++ ) {
7256- int32 available_stack_cell =
7257- (int32 )(loader_ctx -> stack_cell_num - block -> stack_cell_num );
7258-
7259- if (available_stack_cell <= 0 && block -> is_stack_polymorphic )
7260- break ;
7261-
7262- POP_OFFSET_TYPE (wasm_type -> types [param_count - i - 1 ]);
7263- wasm_loader_emit_backspace (loader_ctx , sizeof (int16 ));
7264- }
7265- available_param_count = i ;
72667244
7267- size =
7268- ( uint64 ) available_param_count * ( sizeof ( * cells ) + sizeof ( * src_offsets ) );
7245+ uint64 size = ( uint64 ) param_count * ( sizeof ( * cells ) + sizeof ( * src_offsets ));
7246+ bh_assert ( size > 0 );
72697247
72707248 /* For if block, we also need copy the condition operand offset. */
72717249 if (is_if_block )
72727250 size += sizeof (* cells ) + sizeof (* src_offsets );
72737251
72747252 /* Allocate memory for the emit data */
7275- if ((size > 0 )
7276- && !(emit_data = loader_malloc (size , error_buf , error_buf_size )))
7253+ if (!(emit_data = loader_malloc (size , error_buf , error_buf_size )))
72777254 return false;
72787255
72797256 cells = emit_data ;
72807257 src_offsets = (int16 * )(cells + param_count );
72817258
7259+ if (is_if_block )
7260+ condition_offset = * loader_ctx -> frame_offset ;
7261+
7262+ /* POP original parameter out */
7263+ for (i = 0 ; i < param_count ; i ++ ) {
7264+ POP_OFFSET_TYPE (wasm_type -> types [param_count - i - 1 ]);
7265+ wasm_loader_emit_backspace (loader_ctx , sizeof (int16 ));
7266+ }
72827267 frame_offset = loader_ctx -> frame_offset ;
72837268
72847269 /* Get each param's cell num and src offset */
7285- for (i = 0 ; i < available_param_count ; i ++ ) {
7270+ for (i = 0 ; i < param_count ; i ++ ) {
72867271 cell = (uint8 )wasm_value_type_cell_num (wasm_type -> types [i ]);
72877272 cells [i ] = cell ;
72887273 src_offsets [i ] = * frame_offset ;
72897274 frame_offset += cell ;
72907275 }
7291-
72927276 /* emit copy instruction */
72937277 emit_label (EXT_OP_COPY_STACK_VALUES );
72947278 /* Part a) */
7295- emit_uint32 (loader_ctx , is_if_block ? available_param_count + 1
7296- : available_param_count );
7279+ emit_uint32 (loader_ctx , is_if_block ? param_count + 1 : param_count );
72977280 /* Part b) */
72987281 emit_uint32 (loader_ctx , is_if_block ? wasm_type -> param_cell_num + 1
72997282 : wasm_type -> param_cell_num );
73007283 /* Part c) */
7301- for (i = 0 ; i < available_param_count ; i ++ )
7284+ for (i = 0 ; i < param_count ; i ++ )
73027285 emit_byte (loader_ctx , cells [i ]);
73037286 if (is_if_block )
73047287 emit_byte (loader_ctx , 1 );
73057288
73067289 /* Part d) */
7307- for (i = 0 ; i < available_param_count ; i ++ )
7290+ for (i = 0 ; i < param_count ; i ++ )
73087291 emit_operand (loader_ctx , src_offsets [i ]);
73097292 if (is_if_block )
73107293 emit_operand (loader_ctx , condition_offset );
73117294
73127295 /* Part e) */
73137296 /* Push to dynamic space. The push will emit the dst offset. */
7314- for (i = 0 ; i < available_param_count ; i ++ )
7297+ for (i = 0 ; i < param_count ; i ++ )
73157298 PUSH_OFFSET_TYPE (wasm_type -> types [i ]);
73167299 if (is_if_block )
73177300 PUSH_OFFSET_TYPE (VALUE_TYPE_I32 );
73187301
7319- if (p_available_param_count ) {
7320- * p_available_param_count = available_param_count ;
7321- }
7322-
73237302 ret = true;
73247303
73257304fail :
73267305 /* Free the emit data */
7327- if (emit_data ) {
7328- wasm_runtime_free (emit_data );
7329- }
7306+ wasm_runtime_free (emit_data );
73307307
73317308 return ret ;
73327309}
@@ -7616,6 +7593,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
76167593
76177594 BranchBlock * cur_block = loader_ctx -> frame_csp - 1 ;
76187595#if WASM_ENABLE_FAST_INTERP != 0
7596+ uint32 cell_num ;
76197597 available_params = block_type .u .type -> param_count ;
76207598#endif
76217599 for (i = 0 ; i < block_type .u .type -> param_count ; i ++ ) {
@@ -7633,6 +7611,13 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
76337611
76347612 POP_TYPE (
76357613 wasm_type -> types [wasm_type -> param_count - i - 1 ]);
7614+ #if WASM_ENABLE_FAST_INTERP != 0
7615+ /* decrease the frame_offset pointer accordingly to keep
7616+ * consistent with frame_ref stack */
7617+ cell_num = wasm_value_type_cell_num (
7618+ wasm_type -> types [wasm_type -> param_count - i - 1 ]);
7619+ loader_ctx -> frame_offset -= cell_num ;
7620+ #endif
76367621 }
76377622 }
76387623 PUSH_CSP (LABEL_TYPE_BLOCK + (opcode - WASM_OP_BLOCK ),
@@ -7641,12 +7626,26 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
76417626 /* Pass parameters to block */
76427627 if (BLOCK_HAS_PARAM (block_type )) {
76437628 for (i = 0 ; i < block_type .u .type -> param_count ; i ++ ) {
7644- PUSH_TYPE (block_type .u .type -> types [i ]);
76457629#if WASM_ENABLE_FAST_INTERP != 0
7630+ uint32 cell_num = wasm_value_type_cell_num (
7631+ block_type .u .type -> types [i ]);
76467632 if (i >= available_params ) {
7647- PUSH_OFFSET_TYPE (block_type .u .type -> types [i ]);
7633+ /* If there isn't enough data on stack, push a dummy
7634+ * offset to keep the stack consistent with
7635+ * frame_ref.
7636+ * Since the stack is already in polymorphic state,
7637+ * the opcode will not be executed, so the dummy
7638+ * offset won't cause any error */
7639+ * loader_ctx -> frame_offset ++ = 0 ;
7640+ if (cell_num > 1 ) {
7641+ * loader_ctx -> frame_offset ++ = 0 ;
7642+ }
7643+ }
7644+ else {
7645+ loader_ctx -> frame_offset += cell_num ;
76487646 }
76497647#endif
7648+ PUSH_TYPE (block_type .u .type -> types [i ]);
76507649 }
76517650 }
76527651
@@ -7656,9 +7655,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
76567655
76577656 if (BLOCK_HAS_PARAM (block_type )) {
76587657 /* Make sure params are in dynamic space */
7659- if (!copy_params_to_dynamic_space (loader_ctx , false,
7660- NULL , error_buf ,
7661- error_buf_size ))
7658+ if (!copy_params_to_dynamic_space (
7659+ loader_ctx , false, error_buf , error_buf_size ))
76627660 goto fail ;
76637661 }
76647662
@@ -7691,17 +7689,21 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
76917689 * recover them before entering else branch.
76927690 *
76937691 */
7694- if (if_condition_available && BLOCK_HAS_PARAM (block_type )) {
7692+ if (BLOCK_HAS_PARAM (block_type )) {
76957693 uint64 size ;
76967694
7697- /* skip the if condition operand offset */
7698- wasm_loader_emit_backspace (loader_ctx , sizeof (int16 ));
7695+ /* In polymorphic state, there may be no if condition on
7696+ * the stack, so the offset may not emitted */
7697+ if (if_condition_available ) {
7698+ /* skip the if condition operand offset */
7699+ wasm_loader_emit_backspace (loader_ctx ,
7700+ sizeof (int16 ));
7701+ }
76997702 /* skip the if label */
77007703 skip_label ();
77017704 /* Emit a copy instruction */
77027705 if (!copy_params_to_dynamic_space (
7703- loader_ctx , true, & block -> available_param_num ,
7704- error_buf , error_buf_size ))
7706+ loader_ctx , true, error_buf , error_buf_size ))
77057707 goto fail ;
77067708
77077709 /* Emit the if instruction */
@@ -7722,9 +7724,8 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
77227724 - size / sizeof (int16 ),
77237725 (uint32 )size );
77247726 }
7725- else {
7726- block -> available_param_num = 0 ;
7727- }
7727+
7728+ block -> start_dynamic_offset = loader_ctx -> dynamic_offset ;
77287729
77297730 emit_empty_label_addr_and_frame_ip (PATCH_ELSE );
77307731 emit_empty_label_addr_and_frame_ip (PATCH_END );
@@ -7980,30 +7981,13 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
79807981
79817982#if WASM_ENABLE_FAST_INTERP != 0
79827983 /* Recover top param_count values of frame_offset stack */
7983- if (block -> available_param_num ) {
7984- uint32 available_param_cell_num = 0 ;
7985-
7986- /* total cell num of available parameters */
7987- for (i = 0 ; i < block -> available_param_num ; i ++ ) {
7988- uint32 cell_num = wasm_value_type_cell_num (
7989- block -> block_type .u .type -> types [i ]);
7990-
7991- /* recover dynamic offset */
7992- if (block -> param_frame_offsets [available_param_cell_num ]
7993- >= loader_ctx -> dynamic_offset ) {
7994- loader_ctx -> dynamic_offset =
7995- block -> param_frame_offsets
7996- [available_param_cell_num ]
7997- + cell_num ;
7998- }
7999-
8000- available_param_cell_num += cell_num ;
8001- }
8002-
8003- bh_memcpy_s (
8004- loader_ctx -> frame_offset , available_param_cell_num ,
8005- block -> param_frame_offsets , available_param_cell_num );
8006- loader_ctx -> frame_offset += available_param_cell_num ;
7984+ if (BLOCK_HAS_PARAM ((block_type ))) {
7985+ uint32 size ;
7986+ size = sizeof (int16 ) * block_type .u .type -> param_cell_num ;
7987+ bh_memcpy_s (loader_ctx -> frame_offset , size ,
7988+ block -> param_frame_offsets , size );
7989+ loader_ctx -> frame_offset += (size / sizeof (int16 ));
7990+ loader_ctx -> dynamic_offset = block -> start_dynamic_offset ;
80077991 }
80087992#endif
80097993
0 commit comments