# HG changeset patch # User Petter T. # Date 1707950328 -3600 # Wed Feb 14 23:38:48 2024 +0100 # Branch bytecode-interpreter # Node ID 024ec6194932e7fbb931813ea09a6abdce9df28a # Parent 19973af3ac4287abde785754d3e0ef53707a5d49 Allow more than 255 arguments to index operations in bytecode (bug #65304) Change some opcodes to use 2 bytes for number of args and use them when the number of args is bigger than 255. INDEX_STRUCT_SUBCALL, INDEX_STRUCT_CALL, WORDCMD, WORDCMD_NX and INDEX_OBJ. * pt-bytecode-vm.cc: Use two bytes for number of args for the opcodes * pt-bytecode-walk.cc: Use the opcodes when many args diff -r 19973af3ac42 -r 024ec6194932 libinterp/parse-tree/pt-bytecode-vm.cc --- a/libinterp/parse-tree/pt-bytecode-vm.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/parse-tree/pt-bytecode-vm.cc Wed Feb 14 23:38:48 2024 +0100 @@ -332,7 +332,7 @@ CASE_START (POP_N_INTS) PCHAR () CASE_END () CASE_START (DUP_MOVE) PCHAR () CASE_END () - CASE_START (INDEX_STRUCT_SUBCALL) PCHAR () PCHAR () PCHAR () PCHAR () PCHAR_AS_CHAR () CASE_END () + CASE_START (INDEX_STRUCT_SUBCALL) PCHAR () PCHAR () PCHAR () PSHORT () PCHAR_AS_CHAR () CASE_END () CASE_START (MUL_CST) PCHAR () PCHAR () CASE_END () CASE_START (MUL_CST_DBL) PCHAR () PCHAR () CASE_END () @@ -418,7 +418,7 @@ CASE_START (INDEX_ID1_MATHY_UFUN) PCHAR () PSLOT () PCHAR () CASE_END () - CASE_START (INDEX_OBJ) PCHAR () PCHAR () PWSLOT () PCHAR () PCHAR () CASE_END () + CASE_START (INDEX_OBJ) PCHAR () PCHAR () PWSLOT () PSHORT () PCHAR () CASE_END () CASE_START (FOR_COND) PSLOT () PSHORT () CASE_END () @@ -444,7 +444,7 @@ CASE_START (INDEX_STRUCT_CALL) PCHAR () PWSLOT () - PCHAR () + PSHORT () PCHAR_AS_CHAR () CASE_END () @@ -452,8 +452,8 @@ CASE_START (END_OBJ) PSLOT () PCHAR () PCHAR () CASE_END () - CASE_START (WORDCMD_NX) PSLOT () PCHAR () CASE_END () - CASE_START (WORDCMD) PSLOT () PCHAR () PCHAR () CASE_END () + CASE_START (WORDCMD_NX) PSLOT () PSHORT () CASE_END () + CASE_START (WORDCMD) PSLOT () PCHAR () PSHORT () CASE_END () CASE_START (SET_IGNORE_OUTPUTS) PCHAR () @@ -4215,14 +4215,14 @@ wordcmd_nx: slot = arg0; nargout = bsp[0].i; - n_args_on_stack = *ip++; + n_args_on_stack = POP_CODE_USHORT (); } else if (0) { wordcmd: slot = arg0; nargout = *ip++; - n_args_on_stack = *ip++; + n_args_on_stack = POP_CODE_USHORT (); } // The object to index is before the args on the stack @@ -5711,7 +5711,7 @@ int nargout = arg0; int slot = POP_CODE_USHORT (); - int n_args_on_stack = POP_CODE (); + int n_args_on_stack = POP_CODE_USHORT (); char type = POP_CODE (); // The object being indexed is on the stack under the arguments @@ -5776,9 +5776,9 @@ { // Skip the following subsref. Need to check for nargout extension. if (*ip == static_cast (INSTR::EXT_NARGOUT)) - ip += 7; // Skip EXT_NARGOUT + STRUCT_INDEX_SUBCALL + ip += 8; // Skip EXT_NARGOUT + STRUCT_INDEX_SUBCALL else - ip += 6; // Skip STRUCT_INDEX_SUBCALL + ip += 7; // Skip STRUCT_INDEX_SUBCALL retval = fcn->call (*m_tw, nargout, ovl); } else @@ -6016,7 +6016,7 @@ int nargout = arg0; int has_slot = *ip++; int slot = POP_CODE_USHORT (); - int n_args_on_stack = *ip++; + int n_args_on_stack = POP_CODE_USHORT (); char type = *ip++; // The object to index is before the args on the stack @@ -7001,7 +7001,7 @@ } int i = *ip++; int n = *ip++; - int n_args_on_stack = *ip++; + int n_args_on_stack = POP_CODE_USHORT (); char type = *ip++; // The object to index is before the args on the stack diff -r 19973af3ac42 -r 024ec6194932 libinterp/parse-tree/pt-bytecode-walk.cc --- a/libinterp/parse-tree/pt-bytecode-walk.cc Sun Feb 11 09:40:35 2024 -0500 +++ b/libinterp/parse-tree/pt-bytecode-walk.cc Wed Feb 14 23:38:48 2024 +0100 @@ -3711,7 +3711,7 @@ PUSH_CODE (1); // nargout PUSH_CODE (0); // "has slot" PUSH_WSLOT (0); // The w/e slot - PUSH_CODE (n_args_in_part); + PUSH_CODE_SHORT (n_args_in_part); PUSH_CODE (type); // Write the new active subexpression back to the slot MAYBE_PUSH_WIDE_OPEXT (active_idx_slot); @@ -5193,6 +5193,8 @@ tree_argument_list *args = *arg_lists_it; + bool many_args = args ? args->size () > 255 : false; + if (is_wordcmd) { CHECK (e->is_identifier ()); @@ -5207,7 +5209,7 @@ // The vm need the name of the identifier for function lookups PUSH_SLOT (slot); // Push nargin - PUSH_CODE (args ? args->size () : 0); + PUSH_CODE_SHORT (args ? args->size () : 0); } else { @@ -5216,10 +5218,10 @@ PUSH_SLOT (slot); PUSH_CODE (nargout); // Push nargin - PUSH_CODE (args ? args->size () : 0); + PUSH_CODE_SHORT (args ? args->size () : 0); } } - else if (e->is_identifier () && !(type == '.' && !struct_is_id_dot_id)) + else if (! many_args && e->is_identifier () && !(type == '.' && !struct_is_id_dot_id)) { std::string id_name = e->name (); int slot = SLOT (id_name); @@ -5323,19 +5325,28 @@ } else { - // We are not indexing an id, but e.g.: + // We either indexing an temporary object, e.g. // (foo).() - // I.e. a temporary object. + // or an id with more than 255 arguments. + + int slot = 0; + + if (e->is_identifier ()) + { + std::string id_name = e->name (); + slot = SLOT (id_name); + } + MAYBE_PUSH_ANON_NARGOUT_OPEXT (nargout); PUSH_CODE (INSTR::INDEX_OBJ); PUSH_CODE (nargout); // This is arg0, not used if EXT_NARGOUT is used - PUSH_CODE (0); // "has slot" - PUSH_WSLOT (0); // The w/e slot TODO: Remove? + PUSH_CODE (slot != 0); // "has slot" + PUSH_WSLOT (slot); // Push nargin if (type == '.') - PUSH_CODE (1); // Nargin always one for struct indexing + PUSH_CODE_SHORT (1); // Nargin always one for struct indexing else - PUSH_CODE (args ? args->size () : 0); + PUSH_CODE_SHORT (args ? args->size () : 0); PUSH_CODE (type); } @@ -5542,7 +5553,7 @@ PUSH_WSLOT (0); // slot ignored } - PUSH_CODE (v_n_args[0]); + PUSH_CODE_SHORT (v_n_args[0]); PUSH_CODE (v_types[0]); // '.', '(' or '{' // The first subcall (INDEX_STRUCT_CALL) checks the identifier to see if it is function that should be called. @@ -5558,7 +5569,7 @@ PUSH_CODE (nargout); PUSH_CODE (0); PUSH_CODE (v_n_args.size ()); - PUSH_CODE (v_n_args[0]); + PUSH_CODE_SHORT (v_n_args[0]); PUSH_CODE (v_types[0]); } @@ -5587,7 +5598,7 @@ PUSH_CODE (nargout); PUSH_CODE (cntr); PUSH_CODE (v_n_args.size ()); - PUSH_CODE (v_n_args[cntr]); + PUSH_CODE_SHORT (v_n_args[cntr]); PUSH_CODE (v_types[cntr]); }