@@ -602,21 +602,30 @@ typedef struct JSInlineCache {
602
602
uint32_t hash_bits;
603
603
JSInlineCacheHashSlot **hash;
604
604
JSInlineCacheRingSlot *cache;
605
- uint32_t updated_offset;
606
- BOOL updated;
607
605
} JSInlineCache;
608
606
607
+ #define INLINE_CACHE_MISS ((uint32_t)-1) // sentinel
608
+
609
+ // This is a struct so we don't tie up two argument registers in calls to
610
+ // JS_GetPropertyInternal2 and JS_SetPropertyInternal2 in the common case
611
+ // where there is no IC and therefore no offset to update.
612
+ typedef struct JSInlineCacheUpdate {
613
+ JSInlineCache *ic;
614
+ uint32_t offset;
615
+ } JSInlineCacheUpdate;
616
+
609
617
static JSInlineCache *init_ic(JSContext *ctx);
610
618
static int rebuild_ic(JSContext *ctx, JSInlineCache *ic);
611
619
static int resize_ic_hash(JSContext *ctx, JSInlineCache *ic);
612
620
static int free_ic(JSRuntime *rt, JSInlineCache *ic);
613
- static uint32_t add_ic_slot(JSContext *ctx, JSInlineCache *ic, JSAtom atom, JSObject *object ,
614
- uint32_t prop_offset);
621
+ static void add_ic_slot(JSContext *ctx, JSInlineCacheUpdate *icu ,
622
+ JSAtom atom, JSObject *object, uint32_t prop_offset);
615
623
616
- static int32_t get_ic_prop_offset(JSInlineCache *ic, uint32_t cache_offset ,
617
- JSShape *shape)
624
+ static uint32_t get_ic_prop_offset(const JSInlineCacheUpdate *icu ,
625
+ JSShape *shape)
618
626
{
619
- uint32_t i;
627
+ uint32_t i, cache_offset = icu->offset;
628
+ JSInlineCache *ic = icu->ic;
620
629
JSInlineCacheRingSlot *cr;
621
630
JSShape *shape_slot;
622
631
assert(cache_offset < ic->capacity);
@@ -635,7 +644,7 @@ static int32_t get_ic_prop_offset(JSInlineCache *ic, uint32_t cache_offset,
635
644
}
636
645
}
637
646
638
- return -1 ;
647
+ return INLINE_CACHE_MISS ;
639
648
}
640
649
641
650
static force_inline JSAtom get_ic_atom(JSInlineCache *ic, uint32_t cache_offset)
@@ -7283,7 +7292,8 @@ static int JS_AutoInitProperty(JSContext *ctx, JSObject *p, JSAtom prop,
7283
7292
7284
7293
static JSValue JS_GetPropertyInternal2(JSContext *ctx, JSValue obj,
7285
7294
JSAtom prop, JSValue this_obj,
7286
- JSInlineCache* ic, BOOL throw_ref_error)
7295
+ JSInlineCacheUpdate *icu,
7296
+ BOOL throw_ref_error)
7287
7297
{
7288
7298
JSObject *p;
7289
7299
JSProperty *pr;
@@ -7352,9 +7362,8 @@ static JSValue JS_GetPropertyInternal2(JSContext *ctx, JSValue obj,
7352
7362
continue;
7353
7363
}
7354
7364
} else {
7355
- if (ic && proto_depth == 0 && p->shape->is_hashed) {
7356
- ic->updated = TRUE;
7357
- ic->updated_offset = add_ic_slot(ctx, ic, prop, p, offset);
7365
+ if (icu && proto_depth == 0 && p->shape->is_hashed) {
7366
+ add_ic_slot(ctx, icu, prop, p, offset);
7358
7367
}
7359
7368
return js_dup(pr->u.value);
7360
7369
}
@@ -7444,20 +7453,20 @@ JSValue JS_GetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop)
7444
7453
7445
7454
static JSValue JS_GetPropertyInternalWithIC(JSContext *ctx, JSValue obj,
7446
7455
JSAtom prop, JSValue this_obj,
7447
- JSInlineCache *ic, int32_t offset ,
7456
+ JSInlineCacheUpdate *icu ,
7448
7457
BOOL throw_ref_error)
7449
7458
{
7450
- uint32_t tag;
7459
+ uint32_t tag, offset ;
7451
7460
JSObject *p;
7452
7461
tag = JS_VALUE_GET_TAG(obj);
7453
7462
if (unlikely(tag != JS_TAG_OBJECT))
7454
7463
goto slow_path;
7455
7464
p = JS_VALUE_GET_OBJ(obj);
7456
- offset = get_ic_prop_offset(ic, offset , p->shape);
7457
- if (likely(offset >= 0 ))
7465
+ offset = get_ic_prop_offset(icu , p->shape);
7466
+ if (likely(offset != INLINE_CACHE_MISS ))
7458
7467
return js_dup(p->prop[offset].u.value);
7459
7468
slow_path:
7460
- return JS_GetPropertyInternal2(ctx, obj, prop, this_obj, ic , throw_ref_error);
7469
+ return JS_GetPropertyInternal2(ctx, obj, prop, this_obj, icu , throw_ref_error);
7461
7470
}
7462
7471
7463
7472
static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom)
@@ -8611,9 +8620,9 @@ static void js_free_desc(JSContext *ctx, JSPropertyDescriptor *desc)
8611
8620
the new property is not added and an error is raised.
8612
8621
'obj' must be an object when obj != this_obj.
8613
8622
*/
8614
- static int JS_SetPropertyInternal2(JSContext *ctx, JSValue obj,
8615
- JSAtom prop, JSValue val, JSValue this_obj,
8616
- int flags, JSInlineCache *ic )
8623
+ static int JS_SetPropertyInternal2(JSContext *ctx, JSValue obj, JSAtom prop,
8624
+ JSValue val, JSValue this_obj, int flags ,
8625
+ JSInlineCacheUpdate *icu )
8617
8626
{
8618
8627
JSObject *p, *p1;
8619
8628
JSShapeProperty *prs;
@@ -8649,9 +8658,8 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValue obj,
8649
8658
if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |
8650
8659
JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {
8651
8660
/* fast case */
8652
- if (ic && p->shape->is_hashed) {
8653
- ic->updated = TRUE;
8654
- ic->updated_offset = add_ic_slot(ctx, ic, prop, p, offset);
8661
+ if (icu && p->shape->is_hashed) {
8662
+ add_ic_slot(ctx, icu, prop, p, offset);
8655
8663
}
8656
8664
set_value(ctx, &pr->u.value, val);
8657
8665
return TRUE;
@@ -8876,23 +8884,24 @@ int JS_SetProperty(JSContext *ctx, JSValue this_obj, JSAtom prop, JSValue val)
8876
8884
return JS_SetPropertyInternal2(ctx, this_obj, prop, val, this_obj, JS_PROP_THROW, NULL);
8877
8885
}
8878
8886
8887
+ // XXX(bnoordhuis) only used by OP_put_field_ic, maybe inline at call site
8879
8888
static int JS_SetPropertyInternalWithIC(JSContext *ctx, JSValue this_obj,
8880
8889
JSAtom prop, JSValue val, int flags,
8881
- JSInlineCache *ic, int32_t offset ) {
8882
- uint32_t tag;
8890
+ JSInlineCacheUpdate *icu ) {
8891
+ uint32_t tag, offset ;
8883
8892
JSObject *p;
8884
8893
tag = JS_VALUE_GET_TAG(this_obj);
8885
8894
if (unlikely(tag != JS_TAG_OBJECT))
8886
8895
goto slow_path;
8887
8896
p = JS_VALUE_GET_OBJ(this_obj);
8888
- offset = get_ic_prop_offset(ic, offset , p->shape);
8889
- if (likely(offset >= 0 )) {
8897
+ offset = get_ic_prop_offset(icu , p->shape);
8898
+ if (likely(offset != INLINE_CACHE_MISS )) {
8890
8899
set_value(ctx, &p->prop[offset].u.value, val);
8891
8900
return TRUE;
8892
8901
}
8893
8902
slow_path:
8894
8903
return JS_SetPropertyInternal2(ctx, this_obj, prop, val, this_obj,
8895
- flags, ic );
8904
+ flags, icu );
8896
8905
}
8897
8906
8898
8907
/* flags can be JS_PROP_THROW or JS_PROP_THROW_STRICT */
@@ -16129,16 +16138,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
16129
16138
{
16130
16139
JSValue val;
16131
16140
JSAtom atom;
16141
+ JSInlineCacheUpdate icu;
16132
16142
atom = get_u32(pc);
16133
16143
pc += 4;
16134
16144
sf->cur_pc = pc;
16135
- val = JS_GetPropertyInternal2(ctx, sp[-1], atom, sp[-1], ic, FALSE);
16145
+ icu = (JSInlineCacheUpdate){ic, INLINE_CACHE_MISS};
16146
+ val = JS_GetPropertyInternal2(ctx, sp[-1], atom, sp[-1], &icu, FALSE);
16136
16147
if (unlikely(JS_IsException(val)))
16137
16148
goto exception;
16138
- if (ic && ic->updated == TRUE) {
16139
- ic->updated = FALSE;
16149
+ if (icu.offset != INLINE_CACHE_MISS) {
16140
16150
put_u8(pc - 5, OP_get_field_ic);
16141
- put_u32(pc - 4, ic->updated_offset );
16151
+ put_u32(pc - 4, icu.offset );
16142
16152
JS_FreeAtom(ctx, atom);
16143
16153
}
16144
16154
JS_FreeValue(ctx, sp[-1]);
@@ -16150,33 +16160,37 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
16150
16160
{
16151
16161
JSValue val;
16152
16162
JSAtom atom;
16153
- int32_t ic_offset;
16163
+ uint32_t ic_offset;
16164
+ JSInlineCacheUpdate icu;
16154
16165
ic_offset = get_u32(pc);
16155
16166
atom = get_ic_atom(ic, ic_offset);
16156
16167
pc += 4;
16157
16168
sf->cur_pc = pc;
16158
- val = JS_GetPropertyInternalWithIC(ctx, sp[-1], atom, sp[-1], ic, ic_offset, FALSE) ;
16159
- ic->updated = FALSE;
16169
+ icu = (JSInlineCacheUpdate){ ic, ic_offset} ;
16170
+ val = JS_GetPropertyInternalWithIC(ctx, sp[-1], atom, sp[-1], &icu, FALSE) ;
16160
16171
if (unlikely(JS_IsException(val)))
16161
16172
goto exception;
16173
+ assert(icu.offset == ic_offset);
16162
16174
JS_FreeValue(ctx, sp[-1]);
16163
16175
sp[-1] = val;
16164
16176
}
16165
16177
BREAK;
16178
+
16166
16179
CASE(OP_get_field2):
16167
16180
{
16168
16181
JSValue val;
16169
16182
JSAtom atom;
16183
+ JSInlineCacheUpdate icu;
16170
16184
atom = get_u32(pc);
16171
16185
pc += 4;
16172
16186
sf->cur_pc = pc;
16173
- val = JS_GetPropertyInternal2(ctx, sp[-1], atom, sp[-1], NULL, FALSE);
16187
+ icu = (JSInlineCacheUpdate){ic, INLINE_CACHE_MISS};
16188
+ val = JS_GetPropertyInternal2(ctx, sp[-1], atom, sp[-1], &icu, FALSE);
16174
16189
if (unlikely(JS_IsException(val)))
16175
16190
goto exception;
16176
- if (ic != NULL && ic->updated == TRUE) {
16177
- ic->updated = FALSE;
16191
+ if (icu.offset != INLINE_CACHE_MISS) {
16178
16192
put_u8(pc - 5, OP_get_field2_ic);
16179
- put_u32(pc - 4, ic->updated_offset );
16193
+ put_u32(pc - 4, icu.offset );
16180
16194
JS_FreeAtom(ctx, atom);
16181
16195
}
16182
16196
*sp++ = val;
@@ -16187,15 +16201,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
16187
16201
{
16188
16202
JSValue val;
16189
16203
JSAtom atom;
16190
- int32_t ic_offset;
16204
+ uint32_t ic_offset;
16205
+ JSInlineCacheUpdate icu;
16191
16206
ic_offset = get_u32(pc);
16192
16207
atom = get_ic_atom(ic, ic_offset);
16193
16208
pc += 4;
16194
16209
sf->cur_pc = pc;
16195
- val = JS_GetPropertyInternalWithIC(ctx, sp[-1], atom, sp[-1], ic, ic_offset, FALSE) ;
16196
- ic->updated = FALSE;
16210
+ icu = (JSInlineCacheUpdate){ ic, ic_offset} ;
16211
+ val = JS_GetPropertyInternalWithIC(ctx, sp[-1], atom, sp[-1], &icu, FALSE) ;
16197
16212
if (unlikely(JS_IsException(val)))
16198
16213
goto exception;
16214
+ assert(icu.offset == ic_offset);
16199
16215
*sp++ = val;
16200
16216
}
16201
16217
BREAK;
@@ -16204,21 +16220,22 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
16204
16220
{
16205
16221
int ret;
16206
16222
JSAtom atom;
16223
+ JSInlineCacheUpdate icu;
16207
16224
atom = get_u32(pc);
16208
16225
pc += 4;
16209
16226
sf->cur_pc = pc;
16227
+ icu = (JSInlineCacheUpdate){ic, INLINE_CACHE_MISS};
16210
16228
ret = JS_SetPropertyInternal2(ctx,
16211
16229
sp[-2], atom,
16212
16230
sp[-1], sp[-2],
16213
- JS_PROP_THROW_STRICT, ic );
16231
+ JS_PROP_THROW_STRICT, &icu );
16214
16232
JS_FreeValue(ctx, sp[-2]);
16215
16233
sp -= 2;
16216
16234
if (unlikely(ret < 0))
16217
16235
goto exception;
16218
- if (ic != NULL && ic->updated == TRUE) {
16219
- ic->updated = FALSE;
16236
+ if (icu.offset != INLINE_CACHE_MISS) {
16220
16237
put_u8(pc - 5, OP_put_field_ic);
16221
- put_u32(pc - 4, ic->updated_offset );
16238
+ put_u32(pc - 4, icu.offset );
16222
16239
JS_FreeAtom(ctx, atom);
16223
16240
}
16224
16241
}
@@ -16228,17 +16245,20 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
16228
16245
{
16229
16246
int ret;
16230
16247
JSAtom atom;
16231
- int32_t ic_offset;
16248
+ uint32_t ic_offset;
16249
+ JSInlineCacheUpdate icu;
16232
16250
ic_offset = get_u32(pc);
16233
16251
atom = get_ic_atom(ic, ic_offset);
16234
16252
pc += 4;
16235
16253
sf->cur_pc = pc;
16236
- ret = JS_SetPropertyInternalWithIC(ctx, sp[-2], atom, sp[-1], JS_PROP_THROW_STRICT, ic, ic_offset);
16237
- ic->updated = FALSE;
16254
+ icu = (JSInlineCacheUpdate){ic, ic_offset};
16255
+ ret = JS_SetPropertyInternalWithIC(ctx, sp[-2], atom, sp[-1],
16256
+ JS_PROP_THROW_STRICT, &icu);
16238
16257
JS_FreeValue(ctx, sp[-2]);
16239
16258
sp -= 2;
16240
16259
if (unlikely(ret < 0))
16241
16260
goto exception;
16261
+ assert(icu.offset == ic_offset);
16242
16262
}
16243
16263
BREAK;
16244
16264
@@ -54406,8 +54426,6 @@ JSInlineCache *init_ic(JSContext *ctx)
54406
54426
if (unlikely(!ic->hash))
54407
54427
goto fail;
54408
54428
ic->cache = NULL;
54409
- ic->updated = FALSE;
54410
- ic->updated_offset = 0;
54411
54429
return ic;
54412
54430
fail:
54413
54431
js_free(ctx, ic);
@@ -54490,11 +54508,12 @@ int free_ic(JSRuntime* rt, JSInlineCache *ic)
54490
54508
return 0;
54491
54509
}
54492
54510
54493
- uint32_t add_ic_slot(JSContext *ctx, JSInlineCache *ic, JSAtom atom, JSObject *object ,
54494
- uint32_t prop_offset)
54511
+ static void add_ic_slot(JSContext *ctx, JSInlineCacheUpdate *icu ,
54512
+ JSAtom atom, JSObject *object, uint32_t prop_offset)
54495
54513
{
54496
54514
int32_t i;
54497
54515
uint32_t h;
54516
+ JSInlineCache *ic = icu->ic;
54498
54517
JSInlineCacheHashSlot *ch;
54499
54518
JSInlineCacheRingSlot *cr;
54500
54519
JSShape *sh;
@@ -54523,7 +54542,7 @@ uint32_t add_ic_slot(JSContext *ctx, JSInlineCache *ic, JSAtom atom, JSObject *o
54523
54542
js_free_shape_null(ctx->rt, sh);
54524
54543
cr->prop_offset[i] = prop_offset;
54525
54544
end:
54526
- return ch->index;
54545
+ icu->offset = ch->index;
54527
54546
}
54528
54547
54529
54548
/* CallSite */
0 commit comments