@@ -231,20 +231,18 @@ static void hash_bulk_insert(long argc, const VALUE *argv, VALUE hash)
231231static VALUE vm_render_until_error (VALUE uncast_args )
232232{
233233 vm_render_until_error_args_t * args = (void * )uncast_args ;
234- const VALUE * const_ptr = args -> const_ptr ;
234+ const VALUE * constants = args -> const_ptr ;
235235 const uint8_t * ip = args -> ip ;
236236 vm_t * vm = args -> vm ;
237237 VALUE output = args -> output ;
238+ uint16_t constant_index ;
239+ VALUE constant = Qnil ;
238240 args -> ip = NULL ; // used by vm_render_rescue, NULL to indicate that it isn't in a rescue block
239241
240242 while (true) {
241243 switch (* ip ++ ) {
242244 case OP_LEAVE :
243245 return false;
244-
245- case OP_PUSH_CONST :
246- vm_stack_push (vm , * const_ptr ++ );
247- break ;
248246 case OP_PUSH_NIL :
249247 vm_stack_push (vm , Qnil );
250248 break ;
@@ -268,8 +266,14 @@ static VALUE vm_render_until_error(VALUE uncast_args)
268266 break ;
269267 }
270268 case OP_FIND_STATIC_VAR :
271- vm_stack_push (vm , * const_ptr ++ );
272- /* fallthrough */
269+ {
270+ constant_index = (ip [0 ] << 8 ) | ip [1 ];
271+ constant = constants [constant_index ];
272+ ip += 2 ;
273+ VALUE value = context_find_variable (& vm -> context , constant , Qtrue );
274+ vm_stack_push (vm , value );
275+ break ;
276+ }
273277 case OP_FIND_VAR :
274278 {
275279 VALUE key = vm_stack_pop (vm );
@@ -279,11 +283,16 @@ static VALUE vm_render_until_error(VALUE uncast_args)
279283 }
280284 case OP_LOOKUP_CONST_KEY :
281285 case OP_LOOKUP_COMMAND :
282- vm_stack_push (vm , * const_ptr ++ );
283- /* fallthrough */
286+ {
287+ constant_index = (ip [0 ] << 8 ) | ip [1 ];
288+ constant = constants [constant_index ];
289+ ip += 2 ;
290+ vm_stack_push (vm , constant );
291+ }
292+ /* fallthrough */
284293 case OP_LOOKUP_KEY :
285294 {
286- bool is_command = ip [-1 ] == OP_LOOKUP_COMMAND ;
295+ bool is_command = ip [-3 ] == OP_LOOKUP_COMMAND ;
287296 VALUE key = vm_stack_pop (vm );
288297 VALUE object = vm_stack_pop (vm );
289298 VALUE result = variable_lookup_key (vm -> context .self , object , key , is_command );
@@ -313,13 +322,20 @@ static VALUE vm_render_until_error(VALUE uncast_args)
313322 case OP_BUILTIN_FILTER :
314323 {
315324 VALUE filter_name ;
325+ uint8_t num_args ;
326+
316327 if (ip [-1 ] == OP_FILTER ) {
317- filter_name = * const_ptr ++ ;
328+ constant_index = (ip [0 ] << 8 ) | ip [1 ];
329+ constant = constants [constant_index ];
330+ filter_name = RARRAY_AREF (constant , 0 );
331+ num_args = RARRAY_AREF (constant , 1 );
332+ ip += 2 ;
318333 } else {
319334 assert (ip [-1 ] == OP_BUILTIN_FILTER );
320335 filter_name = builtin_filters [* ip ++ ].sym ;
336+ num_args = * ip ++ ; // includes input argument
321337 }
322- uint8_t num_args = * ip ++ ; // includes input argument
338+
323339 VALUE * args_ptr = vm_stack_pop_n_use_in_place (vm , num_args );
324340 VALUE result = vm_invoke_filter (vm , filter_name , num_args , args_ptr );
325341 vm_stack_push (vm , result );
@@ -360,21 +376,36 @@ static VALUE vm_render_until_error(VALUE uncast_args)
360376 break ;
361377 }
362378
379+ case OP_PUSH_CONST :
380+ {
381+ constant_index = (ip [0 ] << 8 ) | ip [1 ];
382+ constant = constants [constant_index ];
383+ ip += 2 ;
384+ vm_stack_push (vm , constant );
385+ break ;
386+ }
387+
363388 case OP_WRITE_NODE :
364- rb_funcall (cLiquidBlockBody , id_render_node , 3 , vm -> context .self , output , (VALUE )* const_ptr ++ );
389+ {
390+ constant_index = (ip [0 ] << 8 ) | ip [1 ];
391+ constant = constants [constant_index ];
392+ ip += 2 ;
393+ rb_funcall (cLiquidBlockBody , id_render_node , 3 , vm -> context .self , output , constant );
394+
365395 if (RARRAY_LEN (vm -> context .interrupts )) {
366396 return false;
367397 }
398+
368399 resource_limits_increment_write_score (vm -> context .resource_limits , output );
369400 break ;
401+ }
370402 case OP_RENDER_VARIABLE_RESCUE :
371403 // Save state used by vm_render_rescue to rescue from a variable rendering exception
372404 args -> node_line_number = ip ;
373405 // vm_render_rescue will iterate from this instruction to the instruction
374406 // following OP_POP_WRITE_VARIABLE to resume rendering from
375407 ip += 3 ;
376408 args -> ip = ip ;
377- args -> const_ptr = const_ptr ;
378409 break ;
379410 case OP_POP_WRITE :
380411 {
@@ -414,7 +445,7 @@ VALUE liquid_vm_evaluate(VALUE context, vm_assembler_t *code)
414445 return ret ;
415446}
416447
417- void liquid_vm_next_instruction (const uint8_t * * ip_ptr , const VALUE * * const_ptr_ptr )
448+ void liquid_vm_next_instruction (const uint8_t * * ip_ptr )
418449{
419450 const uint8_t * ip = * ip_ptr ;
420451
@@ -436,26 +467,19 @@ void liquid_vm_next_instruction(const uint8_t **ip_ptr, const VALUE **const_ptr_
436467
437468 case OP_BUILTIN_FILTER :
438469 case OP_PUSH_INT16 :
439- ip += 2 ;
440- break ;
441-
442- case OP_WRITE_NODE :
443470 case OP_PUSH_CONST :
471+ case OP_WRITE_NODE :
444472 case OP_FIND_STATIC_VAR :
445473 case OP_LOOKUP_CONST_KEY :
446474 case OP_LOOKUP_COMMAND :
447- (* const_ptr_ptr )++ ;
475+ case OP_FILTER :
476+ ip += 2 ;
448477 break ;
449478
450479 case OP_RENDER_VARIABLE_RESCUE :
451480 ip += 3 ;
452481 break ;
453482
454- case OP_FILTER :
455- ip ++ ;
456- (* const_ptr_ptr )++ ;
457- break ;
458-
459483 case OP_WRITE_RAW_W :
460484 case OP_JUMP_FWD_W :
461485 {
@@ -514,7 +538,7 @@ static VALUE vm_render_rescue(VALUE uncast_args, VALUE exception)
514538 enum opcode last_op ;
515539 do {
516540 last_op = * ip ;
517- liquid_vm_next_instruction (& ip , & render_args -> const_ptr );
541+ liquid_vm_next_instruction (& ip );
518542 } while (last_op != OP_POP_WRITE );
519543 render_args -> ip = ip ;
520544 // remove temporary stack values from variable evaluation
0 commit comments