+ void *code;
+
+ if (ENABLE_THREADED_COMPILER)
+ lightrec_code_alloc_lock(state);
+
+ code = tlsf_malloc(state->tlsf, size);
+
+ if (ENABLE_THREADED_COMPILER)
+ lightrec_code_alloc_unlock(state);
+
+ return code;
+}
+
+static void lightrec_realloc_code(struct lightrec_state *state,
+ void *ptr, size_t size)
+{
+ /* NOTE: 'size' MUST be smaller than the size specified during
+ * the allocation. */
+
+ if (ENABLE_THREADED_COMPILER)
+ lightrec_code_alloc_lock(state);
+
+ tlsf_realloc(state->tlsf, ptr, size);
+
+ if (ENABLE_THREADED_COMPILER)
+ lightrec_code_alloc_unlock(state);
+}
+
+static void lightrec_free_code(struct lightrec_state *state, void *ptr)
+{
+ if (ENABLE_THREADED_COMPILER)
+ lightrec_code_alloc_lock(state);
+
+ tlsf_free(state->tlsf, ptr);
+
+ if (ENABLE_THREADED_COMPILER)
+ lightrec_code_alloc_unlock(state);
+}
+
+static char lightning_code_data[0x80000];
+
+static void * lightrec_emit_code(struct lightrec_state *state,
+ const struct block *block,
+ jit_state_t *_jit, unsigned int *size)
+{
+ bool has_code_buffer = ENABLE_CODE_BUFFER && state->tlsf;
+ jit_word_t code_size, new_code_size;
+ void *code;
+
+ jit_realize();
+
+ if (ENABLE_DISASSEMBLER)
+ jit_set_data(lightning_code_data, sizeof(lightning_code_data), 0);
+ else
+ jit_set_data(NULL, 0, JIT_DISABLE_DATA | JIT_DISABLE_NOTE);
+
+ if (has_code_buffer) {
+ jit_get_code(&code_size);
+ code = lightrec_alloc_code(state, (size_t) code_size);
+
+ if (!code) {
+ if (ENABLE_THREADED_COMPILER) {
+ /* If we're using the threaded compiler, return
+ * an allocation error here. The threaded
+ * compiler will then empty its job queue and
+ * request a code flush using the reaper. */
+ return NULL;
+ }
+
+ /* Remove outdated blocks, and try again */
+ lightrec_remove_outdated_blocks(state->block_cache, block);
+
+ pr_debug("Re-try to alloc %zu bytes...\n", code_size);
+
+ code = lightrec_alloc_code(state, code_size);
+ if (!code) {
+ pr_err("Could not alloc even after removing old blocks!\n");
+ return NULL;
+ }
+ }
+
+ jit_set_code(code, code_size);
+ }
+
+ code = jit_emit();
+
+ jit_get_code(&new_code_size);
+ lightrec_register(MEM_FOR_CODE, new_code_size);