@@ -658,6 +658,8 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo
658658 duk_instr_t * p_instr ;
659659 duk_compiler_instr * q_instr ;
660660 duk_tval * tv ;
661+ duk_bool_t keep_varmap ;
662+ duk_bool_t keep_formals ;
661663
662664 DUK_DDD (DUK_DDDPRINT ("converting duk_compiler_func to function/template" ));
663665
@@ -791,6 +793,25 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo
791793
792794 duk_pop (ctx ); /* 'data' (and everything in it) is reachable through h_res now */
793795
796+ /*
797+ * Init non-property result fields
798+ *
799+ * 'nregs' controls how large a register frame is allocated.
800+ *
801+ * 'nargs' controls how many formal arguments are written to registers:
802+ * r0, ... r(nargs-1). The remaining registers are initialized to
803+ * undefined.
804+ */
805+
806+ DUK_ASSERT (func -> temp_max >= 0 );
807+ h_res -> nregs = (duk_uint16_t ) func -> temp_max ;
808+ h_res -> nargs = (duk_uint16_t ) duk_hobject_get_length (thr , func -> h_argnames );
809+ DUK_ASSERT (h_res -> nregs >= h_res -> nargs ); /* pass2 allocation handles this */
810+ #if defined(DUK_USE_DEBUGGER_SUPPORT )
811+ h_res -> start_line = (duk_uint32_t ) func -> min_line ;
812+ h_res -> end_line = (duk_uint32_t ) func -> max_line ;
813+ #endif
814+
794815 /*
795816 * Init object properties
796817 *
@@ -807,14 +828,20 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo
807828 * after a cleanup. When debugging is enabled, we always need the varmap to
808829 * be able to lookup variables at any point.
809830 */
831+
810832#if defined(DUK_USE_DEBUGGER_SUPPORT )
811- if (1 ) {
833+ DUK_DD (DUK_DDPRINT ("keeping _Varmap because debugger support is enabled" ));
834+ keep_varmap = 1 ;
812835#else
813- if (func -> id_access_slow || /* directly uses slow accesses */
814- func -> may_direct_eval || /* may indirectly slow access through a direct eval */
815- funcs_count > 0 ) { /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
836+ keep_varmap =
837+ func -> id_access_slow || /* directly uses slow accesses */
838+ func -> may_direct_eval || /* may indirectly slow access through a direct eval */
839+ funcs_count > 0 ; /* has inner functions which may slow access (XXX: this can be optimized by looking at the inner functions) */
816840#endif
841+
842+ if (keep_varmap ) {
817843 duk_int_t num_used ;
844+ DUK_DD (DUK_DDPRINT ("keeping _Varmap" ));
818845 duk_dup (ctx , func -> varmap_idx );
819846 num_used = duk__cleanup_varmap (comp_ctx );
820847 DUK_DDD (DUK_DDDPRINT ("cleaned up varmap: %!T (num_used=%ld)" ,
@@ -823,20 +850,35 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo
823850 if (num_used > 0 ) {
824851 duk_xdef_prop_stridx (ctx , -2 , DUK_STRIDX_INT_VARMAP , DUK_PROPDESC_FLAGS_NONE );
825852 } else {
826- DUK_DDD ( DUK_DDDPRINT ("varmap is empty after cleanup -> no need to add" ));
853+ DUK_DD ( DUK_DDPRINT ("varmap is empty after cleanup -> no need to add" ));
827854 duk_pop (ctx );
828855 }
829856 }
830857
831- /* _Formals: omitted if function is guaranteed not to need a (non-strict) arguments object */
832- if (1 ) {
833- /* XXX: Add a proper condition. If formals list is omitted, recheck
834- * handling for 'length' in duk_js_push_closure(); it currently relies
835- * on _Formals being set. Removal may need to be conditional to debugging
836- * being enabled/disabled too.
837- */
858+ /* _Formals: omitted if function is guaranteed not to need a (non-strict)
859+ * arguments object, and _Formals.length matches nargs exactly.
860+ *
861+ * Non-arrow functions can't see an outer function's 'argument' binding
862+ * (because they have their own), but arrow functions can. When arrow
863+ * functions are added, this condition would need to be added:
864+ * inner_arrow_funcs_count > 0 inner arrow functions may access 'arguments'
865+ */
866+ #if defined(DUK_USE_DEBUGGER_SUPPORT )
867+ DUK_DD (DUK_DDPRINT ("keeping _Formals because debugger support is enabled" ));
868+ keep_formals = 1 ;
869+ #else
870+ keep_formals =
871+ func -> id_access_arguments || /* accesses 'arguments', main reason to keep, could check strictness too */
872+ func -> may_direct_eval || /* direct eval -> may access 'arguments' via eval */
873+ duk_get_length (ctx , func -> argnames_idx ) != (duk_size_t ) h_res -> nargs ; /* nargs not enough for closure .length */
874+ #endif
875+
876+ if (keep_formals ) {
877+ DUK_DD (DUK_DDPRINT ("keeping _Formals" ));
838878 duk_dup (ctx , func -> argnames_idx );
839879 duk_xdef_prop_stridx (ctx , -2 , DUK_STRIDX_INT_FORMALS , DUK_PROPDESC_FLAGS_NONE );
880+ } else {
881+ DUK_DD (DUK_DDPRINT ("omitting _Formals, nargs matches _Formals.length, so no properties added" ));
840882 }
841883
842884 /* name */
@@ -920,25 +962,6 @@ DUK_LOCAL void duk__convert_to_func_template(duk_compiler_ctx *comp_ctx, duk_boo
920962 duk_xdef_prop_stridx (ctx , -2 , DUK_STRIDX_FILE_NAME , DUK_PROPDESC_FLAGS_NONE );
921963 }
922964
923- /*
924- * Init remaining result fields
925- *
926- * 'nregs' controls how large a register frame is allocated.
927- *
928- * 'nargs' controls how many formal arguments are written to registers:
929- * r0, ... r(nargs-1). The remaining registers are initialized to
930- * undefined.
931- */
932-
933- DUK_ASSERT (func -> temp_max >= 0 );
934- h_res -> nregs = (duk_uint16_t ) func -> temp_max ;
935- h_res -> nargs = (duk_uint16_t ) duk_hobject_get_length (thr , func -> h_argnames );
936- DUK_ASSERT (h_res -> nregs >= h_res -> nargs ); /* pass2 allocation handles this */
937- #if defined(DUK_USE_DEBUGGER_SUPPORT )
938- h_res -> start_line = (duk_uint32_t ) func -> min_line ;
939- h_res -> end_line = (duk_uint32_t ) func -> max_line ;
940- #endif
941-
942965 DUK_DD (DUK_DDPRINT ("converted function: %!ixT" ,
943966 (duk_tval * ) duk_get_tval (ctx , -1 )));
944967
0 commit comments