Skip to content

Commit aeb3c38

Browse files
committed
Add initial size for NEWOBJ (object literals)
1 parent 5c581f5 commit aeb3c38

6 files changed

Lines changed: 72 additions & 17 deletions

File tree

src-input/duk_heap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,8 @@ struct duk_heap {
574574
duk_int_t stats_ms_emergency_count;
575575
duk_int_t stats_intern_hit;
576576
duk_int_t stats_intern_miss;
577+
duk_int_t stats_object_realloc_props;
578+
duk_int_t stats_object_abandon_array;
577579
duk_int_t stats_getprop_all;
578580
duk_int_t stats_getprop_arrayidx;
579581
duk_int_t stats_getprop_bufobjidx;

src-input/duk_heap_markandsweep.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,8 @@ DUK_LOCAL void duk__dump_stats(duk_heap *heap) {
10651065
(long) heap->stats_ms_emergency_count));
10661066
DUK_D(DUK_DPRINT("stats string intern: hit=%ld, miss=%ld",
10671067
(long) heap->stats_intern_hit, (long) heap->stats_intern_miss));
1068+
DUK_D(DUK_DPRINT("stats object: realloc_props=%ld, abandon_array=%ld",
1069+
(long) heap->stats_object_realloc_props, (long) heap->stats_object_abandon_array));
10681070
DUK_D(DUK_DPRINT("stats getprop: all=%ld, arrayidx=%ld, bufobjidx=%ld, "
10691071
"bufferidx=%ld, bufferlen=%ld, stringidx=%ld, stringlen=%ld, "
10701072
"proxy=%ld, arguments=%ld",

src-input/duk_hobject.h

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,9 @@ DUK_INTERNAL_DECL void duk_hobject_realloc_props(duk_hthread *thr,
868868
duk_uint32_t new_a_size,
869869
duk_uint32_t new_h_size,
870870
duk_bool_t abandon_array);
871+
DUK_INTERNAL_DECL void duk_hobject_resize_props(duk_hthread *thr,
872+
duk_hobject *obj,
873+
duk_uint32_t new_e_size);
871874

872875
/* low-level property functions */
873876
DUK_INTERNAL_DECL void duk_hobject_find_existing_entry(duk_heap *heap, duk_hobject *obj, duk_hstring *key, duk_int_t *e_idx, duk_int_t *h_idx);
@@ -903,22 +906,20 @@ DUK_INTERNAL_DECL duk_bool_t duk_hobject_has_finalizer_fast_raw(duk_hobject *obj
903906
#endif
904907

905908
/* helpers for defineProperty() and defineProperties() */
906-
DUK_INTERNAL_DECL
907-
void duk_hobject_prepare_property_descriptor(duk_context *ctx,
908-
duk_idx_t idx_in,
909-
duk_uint_t *out_defprop_flags,
910-
duk_idx_t *out_idx_value,
911-
duk_hobject **out_getter,
912-
duk_hobject **out_setter);
913-
DUK_INTERNAL_DECL
914-
duk_bool_t duk_hobject_define_property_helper(duk_context *ctx,
915-
duk_uint_t defprop_flags,
916-
duk_hobject *obj,
917-
duk_hstring *key,
918-
duk_idx_t idx_value,
919-
duk_hobject *get,
920-
duk_hobject *set,
921-
duk_bool_t throw_flag);
909+
DUK_INTERNAL_DECL void duk_hobject_prepare_property_descriptor(duk_context *ctx,
910+
duk_idx_t idx_in,
911+
duk_uint_t *out_defprop_flags,
912+
duk_idx_t *out_idx_value,
913+
duk_hobject **out_getter,
914+
duk_hobject **out_setter);
915+
DUK_INTERNAL_DECL duk_bool_t duk_hobject_define_property_helper(duk_context *ctx,
916+
duk_uint_t defprop_flags,
917+
duk_hobject *obj,
918+
duk_hstring *key,
919+
duk_idx_t idx_value,
920+
duk_hobject *get,
921+
duk_hobject *set,
922+
duk_bool_t throw_flag);
922923

923924
/* Object built-in methods */
924925
DUK_INTERNAL_DECL void duk_hobject_object_get_own_property_descriptor(duk_context *ctx, duk_idx_t obj_idx);

src-input/duk_hobject_props.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,8 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
537537
DUK_ASSERT(!DUK_HEAPHDR_HAS_READONLY((duk_heaphdr *) obj));
538538
DUK_ASSERT_VALSTACK_SPACE(thr, DUK__VALSTACK_SPACE);
539539

540+
DUK_STATS_INC(thr->heap, stats_object_realloc_props);
541+
540542
/*
541543
* Pre resize assertions.
542544
*/
@@ -692,6 +694,8 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
692694
*/
693695
DUK_ASSERT(new_a_size == 0);
694696

697+
DUK_STATS_INC(thr->heap, stats_object_abandon_array);
698+
695699
for (i = 0; i < DUK_HOBJECT_GET_ASIZE(obj); i++) {
696700
duk_tval *tv1;
697701
duk_tval *tv2;
@@ -956,6 +960,30 @@ DUK_INTERNAL void duk_hobject_realloc_props(duk_hthread *thr,
956960
* Helpers to resize properties allocation on specific needs.
957961
*/
958962

963+
DUK_INTERNAL void duk_hobject_resize_props(duk_hthread *thr,
964+
duk_hobject *obj,
965+
duk_uint32_t new_e_size) {
966+
duk_uint32_t old_e_size;
967+
duk_uint32_t new_a_size;
968+
duk_uint32_t new_h_size;
969+
970+
DUK_ASSERT(thr != NULL);
971+
DUK_ASSERT(obj != NULL);
972+
973+
old_e_size = DUK_HOBJECT_GET_ESIZE(obj);
974+
if (old_e_size > new_e_size) {
975+
new_e_size = old_e_size;
976+
}
977+
#if defined(DUK_USE_HOBJECT_HASH_PART)
978+
new_h_size = duk__get_default_h_size(new_e_size);
979+
#else
980+
new_h_size = 0;
981+
#endif
982+
new_a_size = DUK_HOBJECT_GET_ASIZE(obj);
983+
984+
duk_hobject_realloc_props(thr, obj, new_e_size, new_a_size, new_h_size, 0);
985+
}
986+
959987
/* Grow entry part allocation for one additional entry. */
960988
DUK_LOCAL void duk__grow_props_for_new_entry_item(duk_hthread *thr, duk_hobject *obj) {
961989
duk_uint32_t old_e_used; /* actually used, non-NULL entries */

src-input/duk_js_compiler.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2955,6 +2955,7 @@ typedef struct {
29552955
duk_reg_t reg_obj;
29562956
duk_reg_t temp_start;
29572957
duk_small_uint_t num_pairs;
2958+
duk_small_uint_t num_total_pairs;
29582959
} duk__objlit_state;
29592960

29602961
DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_state *st) {
@@ -2975,6 +2976,7 @@ DUK_LOCAL void duk__objlit_flush_keys(duk_compiler_ctx *comp_ctx, duk__objlit_st
29752976
st->reg_obj,
29762977
st->temp_start,
29772978
st->num_pairs * 2);
2979+
st->num_total_pairs += st->num_pairs;
29782980
st->num_pairs = 0;
29792981
}
29802982
DUK__SETTEMP(comp_ctx, st->temp_start);
@@ -3006,6 +3008,10 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
30063008
duk_small_uint_t max_init_pairs; /* max # of key-value pairs initialized in one MPUTOBJ set */
30073009
duk_bool_t first; /* first value: comma must not precede the value */
30083010
duk_bool_t is_set, is_get; /* temps */
3011+
duk_int_t pc_newobj;
3012+
#if !defined(DUK_USE_PREFER_SIZE)
3013+
duk_compiler_instr *instr;
3014+
#endif
30093015

30103016
DUK_ASSERT(comp_ctx->prev_token.t == DUK_TOK_LCURLY);
30113017

@@ -3014,8 +3020,10 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
30143020
st.reg_obj = DUK__ALLOCTEMP(comp_ctx); /* target object */
30153021
st.temp_start = DUK__GETTEMP(comp_ctx); /* start of MPUTOBJ argument list */
30163022
st.num_pairs = 0; /* number of key/value pairs emitted for current MPUTOBJ set */
3023+
st.num_total_pairs = 0; /* number of key/value pairs emitted overall */
30173024

3018-
duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj); /* XXX: patch initial size hint afterwards? */
3025+
pc_newobj = duk__get_current_pc(comp_ctx);
3026+
duk__emit_bc(comp_ctx, DUK_OP_NEWOBJ, st.reg_obj);
30193027

30203028
/*
30213029
* Emit initializers in sets of maximum max_init_pairs keys.
@@ -3203,6 +3211,17 @@ DUK_LOCAL void duk__nud_object_literal(duk_compiler_ctx *comp_ctx, duk_ivalue *r
32033211
DUK_ASSERT(st.num_pairs == 0);
32043212
DUK_ASSERT(DUK__GETTEMP(comp_ctx) == st.temp_start);
32053213

3214+
/* Update initial size for NEWOBJ. The init size doesn't need to be
3215+
* exact as the purpose is just to avoid object resizes in common
3216+
* cases. The size is capped to field A limit, and will be too high
3217+
* if the object literal contains duplicate keys (this is harmless but
3218+
* increases memory traffic if the object is compacted later on).
3219+
*/
3220+
#if !defined(DUK_USE_PREFER_SIZE)
3221+
instr = duk__get_instr_ptr(comp_ctx, pc_newobj);
3222+
instr->ins |= DUK_ENC_OP_A(0, st.num_total_pairs > 255 ? 255 : st.num_total_pairs);
3223+
#endif
3224+
32063225
DUK_ASSERT(comp_ctx->curr_token.t == DUK_TOK_RCURLY);
32073226
duk__advance(comp_ctx);
32083227

src-input/duk_js_executor.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4741,6 +4741,9 @@ DUK_LOCAL DUK_NOINLINE DUK_HOT void duk__js_execute_bytecode_inner(duk_hthread *
47414741
case DUK_OP_NEWOBJ: {
47424742
duk_context *ctx = (duk_context *) thr;
47434743
duk_push_object(ctx);
4744+
#if !defined(DUK_USE_PREFER_SIZE)
4745+
duk_hobject_resize_props(thr, duk_known_hobject(ctx, -1), DUK_DEC_A(ins));
4746+
#endif
47444747
DUK__REPLACE_TOP_BC_BREAK();
47454748
}
47464749

0 commit comments

Comments
 (0)