Skip to content

Commit f89d760

Browse files
committed
Avoid concurrent frame prepare/validate.
While the validation itself is idempotent, the assigning of a lexotic pool index decidedly is not. Should fix a crash reported by nwc10++.
1 parent 04f336d commit f89d760

File tree

1 file changed

+33
-24
lines changed

1 file changed

+33
-24
lines changed

src/core/frame.c

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,45 @@
55
* bytecode. */
66
static void prepare_and_verify_static_frame(MVMThreadContext *tc, MVMStaticFrame *static_frame) {
77
MVMStaticFrameBody *static_frame_body = &static_frame->body;
8+
MVMCompUnit *cu = static_frame_body->cu;
89

910
/* Ensure the frame is fully deserialized. */
1011
if (!static_frame_body->fully_deserialized)
11-
MVM_bytecode_finish_frame(tc, static_frame_body->cu, static_frame, 0);
12-
13-
/* Work size is number of locals/registers plus size of the maximum
14-
* call site argument list. */
15-
static_frame_body->work_size = sizeof(MVMRegister) *
16-
(static_frame_body->num_locals + static_frame_body->cu->body.max_callsite_size);
17-
18-
/* Validate the bytecode. */
19-
MVM_validate_static_frame(tc, static_frame);
20-
21-
/* Obtain an index to each threadcontext's lexotic pool table */
22-
static_frame_body->pool_index = MVM_incr(&tc->instance->num_frames_run);
12+
MVM_bytecode_finish_frame(tc, cu, static_frame, 0);
13+
14+
/* Take compilation unit lock, to make sure we don't race to do the
15+
* frame preparation/verification work. */
16+
MVM_reentrantmutex_lock(tc, (MVMReentrantMutex *)cu->body.update_mutex);
17+
if (static_frame->body.instrumentation_level == 0) {
18+
/* Work size is number of locals/registers plus size of the maximum
19+
* call site argument list. */
20+
static_frame_body->work_size = sizeof(MVMRegister) *
21+
(static_frame_body->num_locals + static_frame_body->cu->body.max_callsite_size);
22+
23+
/* Validate the bytecode. */
24+
MVM_validate_static_frame(tc, static_frame);
25+
26+
/* Obtain an index to each threadcontext's lexotic pool table */
27+
static_frame_body->pool_index = MVM_incr(&tc->instance->num_frames_run);
28+
29+
/* Check if we have any state var lexicals. */
30+
if (static_frame_body->static_env_flags) {
31+
MVMuint8 *flags = static_frame_body->static_env_flags;
32+
MVMint64 numlex = static_frame_body->num_lexicals;
33+
MVMint64 i;
34+
for (i = 0; i < numlex; i++)
35+
if (flags[i] == 2) {
36+
static_frame_body->has_state_vars = 1;
37+
break;
38+
}
39+
}
2340

24-
/* Check if we have any state var lexicals. */
25-
if (static_frame_body->static_env_flags) {
26-
MVMuint8 *flags = static_frame_body->static_env_flags;
27-
MVMint64 numlex = static_frame_body->num_lexicals;
28-
MVMint64 i;
29-
for (i = 0; i < numlex; i++)
30-
if (flags[i] == 2) {
31-
static_frame_body->has_state_vars = 1;
32-
break;
33-
}
41+
/* Set its spesh threshold. */
42+
static_frame_body->spesh_threshold = MVM_spesh_threshold(tc, static_frame);
3443
}
3544

36-
/* Set its spesh threshold. */
37-
static_frame_body->spesh_threshold = MVM_spesh_threshold(tc, static_frame);
45+
/* Unlock, now we're finished. */
46+
MVM_reentrantmutex_unlock(tc, (MVMReentrantMutex *)cu->body.update_mutex);
3847
}
3948

4049
/* When we don't match the current instrumentation level, we hit this. It may

0 commit comments

Comments
 (0)