aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Makefile4
-rw-r--r--src/Makefile.dep50
-rw-r--r--src/lib_aux.c8
-rw-r--r--src/lib_math.c53
-rw-r--r--src/lj_alloc.c83
-rw-r--r--src/lj_alloc.h3
-rw-r--r--src/lj_arch.h15
-rw-r--r--src/lj_def.h5
-rw-r--r--src/lj_ffrecord.c2
-rw-r--r--src/lj_ir.c2
-rw-r--r--src/lj_ircall.h2
-rw-r--r--src/lj_jit.h13
-rw-r--r--src/lj_lib.h5
-rw-r--r--src/lj_mcode.c41
-rw-r--r--src/lj_obj.h1
-rw-r--r--src/lj_prng.c225
-rw-r--r--src/lj_prng.h24
-rw-r--r--src/lj_record.c3
-rw-r--r--src/lj_state.c38
-rw-r--r--src/lj_state.h2
-rw-r--r--src/lj_trace.c3
-rw-r--r--src/ljamalg.c1
22 files changed, 410 insertions, 173 deletions
diff --git a/src/Makefile b/src/Makefile
index 667fff56..6a9de5db 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -485,8 +485,8 @@ LJLIB_C= $(LJLIB_O:.o=.c)
485 485
486LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ 486LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
487 lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ 487 lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
488 lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \ 488 lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \
489 lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \ 489 lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \
490 lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ 490 lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
491 lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ 491 lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
492 lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ 492 lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
diff --git a/src/Makefile.dep b/src/Makefile.dep
index 03dba96b..3f26599e 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -1,6 +1,6 @@
1lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ 1lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
2 lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \ 2 lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \
3 lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lj_alloc.h 3 lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h
4lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 4lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
5 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \ 5 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \
6 lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \ 6 lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \
@@ -28,7 +28,7 @@ lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
28 lj_target.h lj_target_*.h lj_trace.h lj_dispatch.h lj_traceerr.h \ 28 lj_target.h lj_target_*.h lj_trace.h lj_dispatch.h lj_traceerr.h \
29 lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h 29 lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h
30lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 30lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
31 lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h 31 lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_prng.h lj_libdef.h
32lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ 32lib_os.o: lib_os.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
33 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_lib.h \ 33 lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_lib.h \
34 lj_libdef.h 34 lj_libdef.h
@@ -41,7 +41,8 @@ lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
41lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ 41lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
42 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \ 42 lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \
43 lj_tab.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h 43 lj_tab.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
44lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h 44lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h \
45 lj_prng.h
45lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 46lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
46 lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \ 47 lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \
47 lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ 48 lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \
@@ -126,7 +127,7 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
126lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 127lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
127 lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ 128 lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \
128 lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \ 129 lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \
129 lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h 130 lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_prng.h
130lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 131lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
131 lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \ 132 lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \
132 lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \ 133 lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \
@@ -140,7 +141,7 @@ lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
140 lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h 141 lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h
141lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 142lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
142 lj_gc.h lj_err.h lj_errmsg.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h \ 143 lj_gc.h lj_err.h lj_errmsg.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h \
143 lj_dispatch.h lj_bc.h lj_traceerr.h lj_vm.h 144 lj_dispatch.h lj_bc.h lj_traceerr.h lj_prng.h lj_vm.h
144lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 145lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
145 lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_meta.h lj_frame.h \ 146 lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_meta.h lj_frame.h \
146 lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h 147 lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h
@@ -172,11 +173,12 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
172lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 173lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
173 lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \ 174 lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \
174 lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h 175 lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h
176lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h
175lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 177lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
176 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ 178 lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
177 lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \ 179 lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \
178 lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \ 180 lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
179 lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h 181 lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h
180lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 182lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
181 lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ 183 lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \
182 lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ 184 lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
@@ -184,7 +186,8 @@ lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
184lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 186lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
185 lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h \ 187 lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h \
186 lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_trace.h lj_jit.h \ 188 lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_trace.h lj_jit.h \
187 lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_alloc.h luajit.h 189 lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \
190 lj_alloc.h luajit.h
188lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 191lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
189 lj_err.h lj_errmsg.h lj_str.h lj_char.h 192 lj_err.h lj_errmsg.h lj_str.h lj_char.h
190lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 193lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
@@ -199,7 +202,7 @@ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
199 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_frame.h lj_bc.h \ 202 lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_frame.h lj_bc.h \
200 lj_state.h lj_ir.h lj_jit.h lj_iropt.h lj_mcode.h lj_trace.h \ 203 lj_state.h lj_ir.h lj_jit.h lj_iropt.h lj_mcode.h lj_trace.h \
201 lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \ 204 lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \
202 lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h 205 lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h
203lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 206lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
204 lj_gc.h lj_udata.h 207 lj_gc.h lj_udata.h
205lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 208lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
@@ -214,21 +217,22 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \
214 lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \ 217 lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \
215 lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \ 218 lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \
216 lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \ 219 lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \
217 lj_state.c lj_lex.h lj_alloc.h luajit.h lj_dispatch.c lj_ccallback.h \ 220 lj_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \
218 lj_profile.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c \ 221 lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \
219 lj_strfmt.c lj_strfmt_num.c lj_api.c lj_profile.c lj_lex.c lualib.h \ 222 lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \
220 lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c \ 223 lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \
221 lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h \ 224 lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \
222 lj_ccallback.c lj_target.h lj_target_*.h lj_mcode.h lj_carith.c \ 225 lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \
223 lj_carith.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c \ 226 lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \
224 lj_ircall.h lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h \ 227 lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \
225 lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c \ 228 lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
226 lj_opt_sink.c lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h \ 229 lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \
227 lj_crecord.c lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h \ 230 lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
228 lj_emit_*.h lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c \ 231 lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \
229 lib_aux.c lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c \ 232 lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \
230 lib_io.c lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c \ 233 lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
231 lib_ffi.c lib_init.c 234 lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \
235 lib_init.c
232luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h 236luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
233host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ 237host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \
234 lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ 238 lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \
diff --git a/src/lib_aux.c b/src/lib_aux.c
index 8f10e23c..35866f8d 100644
--- a/src/lib_aux.c
+++ b/src/lib_aux.c
@@ -345,17 +345,13 @@ LUALIB_API lua_State *luaL_newstate(void)
345 345
346#else 346#else
347 347
348#include "lj_alloc.h"
349
350LUALIB_API lua_State *luaL_newstate(void) 348LUALIB_API lua_State *luaL_newstate(void)
351{ 349{
352 lua_State *L; 350 lua_State *L;
353 void *ud = lj_alloc_create();
354 if (ud == NULL) return NULL;
355#if LJ_64 && !LJ_GC64 351#if LJ_64 && !LJ_GC64
356 L = lj_state_newstate(lj_alloc_f, ud); 352 L = lj_state_newstate(LJ_ALLOCF_INTERNAL, NULL);
357#else 353#else
358 L = lua_newstate(lj_alloc_f, ud); 354 L = lua_newstate(LJ_ALLOCF_INTERNAL, NULL);
359#endif 355#endif
360 if (L) G(L)->panic = panic; 356 if (L) G(L)->panic = panic;
361 return L; 357 return L;
diff --git a/src/lib_math.c b/src/lib_math.c
index 4cc2ba6e..95b7d460 100644
--- a/src/lib_math.c
+++ b/src/lib_math.c
@@ -15,6 +15,7 @@
15#include "lj_obj.h" 15#include "lj_obj.h"
16#include "lj_lib.h" 16#include "lj_lib.h"
17#include "lj_vm.h" 17#include "lj_vm.h"
18#include "lj_prng.h"
18 19
19/* ------------------------------------------------------------------------ */ 20/* ------------------------------------------------------------------------ */
20 21
@@ -105,34 +106,11 @@ LJLIB_PUSH(1e310) LJLIB_SET(huge)
105** Full-period ME-CF generator with L=64, J=4, k=223, N1=49. 106** Full-period ME-CF generator with L=64, J=4, k=223, N1=49.
106*/ 107*/
107 108
108/* PRNG state. */
109struct RandomState {
110 uint64_t gen[4]; /* State of the 4 LFSR generators. */
111 int valid; /* State is valid. */
112};
113
114/* Union needed for bit-pattern conversion between uint64_t and double. */ 109/* Union needed for bit-pattern conversion between uint64_t and double. */
115typedef union { uint64_t u64; double d; } U64double; 110typedef union { uint64_t u64; double d; } U64double;
116 111
117/* Update generator i and compute a running xor of all states. */ 112/* PRNG seeding function. */
118#define TW223_GEN(i, k, q, s) \ 113static void random_seed(PRNGState *rs, double d)
119 z = rs->gen[i]; \
120 z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \
121 r ^= z; rs->gen[i] = z;
122
123/* PRNG step function. Returns a double in the range 1.0 <= d < 2.0. */
124LJ_NOINLINE uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs)
125{
126 uint64_t z, r = 0;
127 TW223_GEN(0, 63, 31, 18)
128 TW223_GEN(1, 58, 19, 28)
129 TW223_GEN(2, 55, 24, 7)
130 TW223_GEN(3, 47, 21, 8)
131 return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000);
132}
133
134/* PRNG initialization function. */
135static void random_init(RandomState *rs, double d)
136{ 114{
137 uint32_t r = 0x11090601; /* 64-k[i] as four 8 bit constants. */ 115 uint32_t r = 0x11090601; /* 64-k[i] as four 8 bit constants. */
138 int i; 116 int i;
@@ -141,24 +119,22 @@ static void random_init(RandomState *rs, double d)
141 uint32_t m = 1u << (r&255); 119 uint32_t m = 1u << (r&255);
142 r >>= 8; 120 r >>= 8;
143 u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354; 121 u.d = d = d * 3.14159265358979323846 + 2.7182818284590452354;
144 if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of gen[i] are non-zero. */ 122 if (u.u64 < m) u.u64 += m; /* Ensure k[i] MSB of u[i] are non-zero. */
145 rs->gen[i] = u.u64; 123 rs->u[i] = u.u64;
146 } 124 }
147 rs->valid = 1;
148 for (i = 0; i < 10; i++) 125 for (i = 0; i < 10; i++)
149 lj_math_random_step(rs); 126 (void)lj_prng_u64(rs);
150} 127}
151 128
152/* PRNG extract function. */ 129/* PRNG extract function. */
153LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */ 130LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */
154LJLIB_CF(math_random) LJLIB_REC(.) 131LJLIB_CF(math_random) LJLIB_REC(.)
155{ 132{
156 int n = (int)(L->top - L->base); 133 int n = (int)(L->top - L->base);
157 RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); 134 PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
158 U64double u; 135 U64double u;
159 double d; 136 double d;
160 if (LJ_UNLIKELY(!rs->valid)) random_init(rs, 0.0); 137 u.u64 = lj_prng_u64d(rs);
161 u.u64 = lj_math_random_step(rs);
162 d = u.d - 1.0; 138 d = u.d - 1.0;
163 if (n > 0) { 139 if (n > 0) {
164#if LJ_DUALNUM 140#if LJ_DUALNUM
@@ -203,11 +179,11 @@ LJLIB_CF(math_random) LJLIB_REC(.)
203} 179}
204 180
205/* PRNG seed function. */ 181/* PRNG seed function. */
206LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */ 182LJLIB_PUSH(top-2) /* Upvalue holds userdata with PRNGState. */
207LJLIB_CF(math_randomseed) 183LJLIB_CF(math_randomseed)
208{ 184{
209 RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1)))); 185 PRNGState *rs = (PRNGState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
210 random_init(rs, lj_lib_checknum(L, 1)); 186 random_seed(rs, lj_lib_checknum(L, 1));
211 return 0; 187 return 0;
212} 188}
213 189
@@ -217,9 +193,8 @@ LJLIB_CF(math_randomseed)
217 193
218LUALIB_API int luaopen_math(lua_State *L) 194LUALIB_API int luaopen_math(lua_State *L)
219{ 195{
220 RandomState *rs; 196 PRNGState *rs = (PRNGState *)lua_newuserdata(L, sizeof(PRNGState));
221 rs = (RandomState *)lua_newuserdata(L, sizeof(RandomState)); 197 lj_prng_seed_fixed(rs);
222 rs->valid = 0; /* Use lazy initialization to save some time on startup. */
223 LJ_LIB_REG(L, LUA_MATHLIBNAME, math); 198 LJ_LIB_REG(L, LUA_MATHLIBNAME, math);
224 return 1; 199 return 1;
225} 200}
diff --git a/src/lj_alloc.c b/src/lj_alloc.c
index 70ca1e3b..bf2ae847 100644
--- a/src/lj_alloc.c
+++ b/src/lj_alloc.c
@@ -31,6 +31,7 @@
31#include "lj_def.h" 31#include "lj_def.h"
32#include "lj_arch.h" 32#include "lj_arch.h"
33#include "lj_alloc.h" 33#include "lj_alloc.h"
34#include "lj_prng.h"
34 35
35#ifndef LUAJIT_USE_SYSMALLOC 36#ifndef LUAJIT_USE_SYSMALLOC
36 37
@@ -140,7 +141,7 @@ static void init_mmap(void)
140#define INIT_MMAP() init_mmap() 141#define INIT_MMAP() init_mmap()
141 142
142/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */ 143/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
143static void *CALL_MMAP(size_t size) 144static void *mmap_plain(size_t size)
144{ 145{
145 DWORD olderr = GetLastError(); 146 DWORD olderr = GetLastError();
146 void *ptr = NULL; 147 void *ptr = NULL;
@@ -164,7 +165,7 @@ static void *direct_mmap(size_t size)
164#else 165#else
165 166
166/* Win32 MMAP via VirtualAlloc */ 167/* Win32 MMAP via VirtualAlloc */
167static void *CALL_MMAP(size_t size) 168static void *mmap_plain(size_t size)
168{ 169{
169 DWORD olderr = GetLastError(); 170 DWORD olderr = GetLastError();
170 void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); 171 void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
@@ -184,7 +185,8 @@ static void *direct_mmap(size_t size)
184 185
185#endif 186#endif
186 187
187#define DIRECT_MMAP(size) direct_mmap(size) 188#define CALL_MMAP(prng, size) mmap_plain(size)
189#define DIRECT_MMAP(prng, size) direct_mmap(size)
188 190
189/* This function supports releasing coalesed segments */ 191/* This function supports releasing coalesed segments */
190static int CALL_MUNMAP(void *ptr, size_t size) 192static int CALL_MUNMAP(void *ptr, size_t size)
@@ -228,30 +230,10 @@ static int CALL_MUNMAP(void *ptr, size_t size)
228 230
229#define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000) 231#define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000)
230 232
231/* No point in a giant ifdef mess. Just try to open /dev/urandom. 233static void *mmap_probe(PRNGState *rs, size_t size)
232** It doesn't really matter if this fails, since we get some ASLR bits from
233** every unsuitable allocation, too. And we prefer linear allocation, anyway.
234*/
235#include <fcntl.h>
236#include <unistd.h>
237
238static uintptr_t mmap_probe_seed(void)
239{
240 uintptr_t val;
241 int fd = open("/dev/urandom", O_RDONLY);
242 if (fd != -1) {
243 int ok = ((size_t)read(fd, &val, sizeof(val)) == sizeof(val));
244 (void)close(fd);
245 if (ok) return val;
246 }
247 return 1; /* Punt. */
248}
249
250static void *mmap_probe(size_t size)
251{ 234{
252 /* Hint for next allocation. Doesn't need to be thread-safe. */ 235 /* Hint for next allocation. Doesn't need to be thread-safe. */
253 static uintptr_t hint_addr = 0; 236 static uintptr_t hint_addr = 0;
254 static uintptr_t hint_prng = 0;
255 int olderr = errno; 237 int olderr = errno;
256 int retry; 238 int retry;
257 for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) { 239 for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) {
@@ -283,15 +265,8 @@ static void *mmap_probe(size_t size)
283 } 265 }
284 } 266 }
285 /* Finally, try pseudo-random probing. */ 267 /* Finally, try pseudo-random probing. */
286 if (LJ_UNLIKELY(hint_prng == 0)) { 268 do {
287 hint_prng = mmap_probe_seed(); 269 hint_addr = lj_prng_u64(rs) & (((uintptr_t)1<<LJ_ALLOC_MBITS)-LJ_PAGESIZE);
288 }
289 /* The unsuitable address we got has some ASLR PRNG bits. */
290 hint_addr ^= addr & ~((uintptr_t)(LJ_PAGESIZE-1));
291 do { /* The PRNG itself is very weak, but see above. */
292 hint_prng = hint_prng * 1103515245 + 12345;
293 hint_addr ^= hint_prng * (uintptr_t)LJ_PAGESIZE;
294 hint_addr &= (((uintptr_t)1 << LJ_ALLOC_MBITS)-1);
295 } while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER); 270 } while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER);
296 } 271 }
297 errno = olderr; 272 errno = olderr;
@@ -308,12 +283,16 @@ static void *mmap_probe(size_t size)
308#define LJ_ALLOC_MMAP32_START ((uintptr_t)0) 283#define LJ_ALLOC_MMAP32_START ((uintptr_t)0)
309#endif 284#endif
310 285
286#if LJ_ALLOC_MMAP_PROBE
287static void *mmap_map32(PRNGState *rs, size_t size)
288#else
311static void *mmap_map32(size_t size) 289static void *mmap_map32(size_t size)
290#endif
312{ 291{
313#if LJ_ALLOC_MMAP_PROBE 292#if LJ_ALLOC_MMAP_PROBE
314 static int fallback = 0; 293 static int fallback = 0;
315 if (fallback) 294 if (fallback)
316 return mmap_probe(size); 295 return mmap_probe(rs, size);
317#endif 296#endif
318 { 297 {
319 int olderr = errno; 298 int olderr = errno;
@@ -323,7 +302,7 @@ static void *mmap_map32(size_t size)
323#if LJ_ALLOC_MMAP_PROBE 302#if LJ_ALLOC_MMAP_PROBE
324 if (ptr == MFAIL) { 303 if (ptr == MFAIL) {
325 fallback = 1; 304 fallback = 1;
326 return mmap_probe(size); 305 return mmap_probe(rs, size);
327 } 306 }
328#endif 307#endif
329 return ptr; 308 return ptr;
@@ -333,17 +312,22 @@ static void *mmap_map32(size_t size)
333#endif 312#endif
334 313
335#if LJ_ALLOC_MMAP32 314#if LJ_ALLOC_MMAP32
336#define CALL_MMAP(size) mmap_map32(size) 315#if LJ_ALLOC_MMAP_PROBE
316#define CALL_MMAP(prng, size) mmap_map32(prng, size)
317#else
318#define CALL_MMAP(prng, size) mmap_map32(size)
319#endif
337#elif LJ_ALLOC_MMAP_PROBE 320#elif LJ_ALLOC_MMAP_PROBE
338#define CALL_MMAP(size) mmap_probe(size) 321#define CALL_MMAP(prng, size) mmap_probe(prng, size)
339#else 322#else
340static void *CALL_MMAP(size_t size) 323static void *mmap_plain(size_t size)
341{ 324{
342 int olderr = errno; 325 int olderr = errno;
343 void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0); 326 void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
344 errno = olderr; 327 errno = olderr;
345 return ptr; 328 return ptr;
346} 329}
330#define CALL_MMAP(prng, size) mmap_plain(size)
347#endif 331#endif
348 332
349#if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4 333#if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
@@ -396,7 +380,7 @@ static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags)
396#endif 380#endif
397 381
398#ifndef DIRECT_MMAP 382#ifndef DIRECT_MMAP
399#define DIRECT_MMAP(s) CALL_MMAP(s) 383#define DIRECT_MMAP(prng, s) CALL_MMAP(prng, s)
400#endif 384#endif
401 385
402#ifndef CALL_MREMAP 386#ifndef CALL_MREMAP
@@ -555,6 +539,7 @@ struct malloc_state {
555 mchunkptr smallbins[(NSMALLBINS+1)*2]; 539 mchunkptr smallbins[(NSMALLBINS+1)*2];
556 tbinptr treebins[NTREEBINS]; 540 tbinptr treebins[NTREEBINS];
557 msegment seg; 541 msegment seg;
542 PRNGState *prng;
558}; 543};
559 544
560typedef struct malloc_state *mstate; 545typedef struct malloc_state *mstate;
@@ -837,11 +822,11 @@ static int has_segment_link(mstate m, msegmentptr ss)
837 822
838/* ----------------------- Direct-mmapping chunks ----------------------- */ 823/* ----------------------- Direct-mmapping chunks ----------------------- */
839 824
840static void *direct_alloc(size_t nb) 825static void *direct_alloc(mstate m, size_t nb)
841{ 826{
842 size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); 827 size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
843 if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */ 828 if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */
844 char *mm = (char *)(DIRECT_MMAP(mmsize)); 829 char *mm = (char *)(DIRECT_MMAP(m->prng, mmsize));
845 if (mm != CMFAIL) { 830 if (mm != CMFAIL) {
846 size_t offset = align_offset(chunk2mem(mm)); 831 size_t offset = align_offset(chunk2mem(mm));
847 size_t psize = mmsize - offset - DIRECT_FOOT_PAD; 832 size_t psize = mmsize - offset - DIRECT_FOOT_PAD;
@@ -853,6 +838,7 @@ static void *direct_alloc(size_t nb)
853 return chunk2mem(p); 838 return chunk2mem(p);
854 } 839 }
855 } 840 }
841 UNUSED(m);
856 return NULL; 842 return NULL;
857} 843}
858 844
@@ -1001,7 +987,7 @@ static void *alloc_sys(mstate m, size_t nb)
1001 987
1002 /* Directly map large chunks */ 988 /* Directly map large chunks */
1003 if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) { 989 if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) {
1004 void *mem = direct_alloc(nb); 990 void *mem = direct_alloc(m, nb);
1005 if (mem != 0) 991 if (mem != 0)
1006 return mem; 992 return mem;
1007 } 993 }
@@ -1010,7 +996,7 @@ static void *alloc_sys(mstate m, size_t nb)
1010 size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; 996 size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
1011 size_t rsize = granularity_align(req); 997 size_t rsize = granularity_align(req);
1012 if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */ 998 if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */
1013 char *mp = (char *)(CALL_MMAP(rsize)); 999 char *mp = (char *)(CALL_MMAP(m->prng, rsize));
1014 if (mp != CMFAIL) { 1000 if (mp != CMFAIL) {
1015 tbase = mp; 1001 tbase = mp;
1016 tsize = rsize; 1002 tsize = rsize;
@@ -1237,12 +1223,13 @@ static void *tmalloc_small(mstate m, size_t nb)
1237 1223
1238/* ----------------------------------------------------------------------- */ 1224/* ----------------------------------------------------------------------- */
1239 1225
1240void *lj_alloc_create(void) 1226void *lj_alloc_create(PRNGState *rs)
1241{ 1227{
1242 size_t tsize = DEFAULT_GRANULARITY; 1228 size_t tsize = DEFAULT_GRANULARITY;
1243 char *tbase; 1229 char *tbase;
1244 INIT_MMAP(); 1230 INIT_MMAP();
1245 tbase = (char *)(CALL_MMAP(tsize)); 1231 UNUSED(rs);
1232 tbase = (char *)(CALL_MMAP(rs, tsize));
1246 if (tbase != CMFAIL) { 1233 if (tbase != CMFAIL) {
1247 size_t msize = pad_request(sizeof(struct malloc_state)); 1234 size_t msize = pad_request(sizeof(struct malloc_state));
1248 mchunkptr mn; 1235 mchunkptr mn;
@@ -1261,6 +1248,12 @@ void *lj_alloc_create(void)
1261 return NULL; 1248 return NULL;
1262} 1249}
1263 1250
1251void lj_alloc_setprng(void *msp, PRNGState *rs)
1252{
1253 mstate ms = (mstate)msp;
1254 ms->prng = rs;
1255}
1256
1264void lj_alloc_destroy(void *msp) 1257void lj_alloc_destroy(void *msp)
1265{ 1258{
1266 mstate ms = (mstate)msp; 1259 mstate ms = (mstate)msp;
diff --git a/src/lj_alloc.h b/src/lj_alloc.h
index f87a7cf3..669f50b7 100644
--- a/src/lj_alloc.h
+++ b/src/lj_alloc.h
@@ -9,7 +9,8 @@
9#include "lj_def.h" 9#include "lj_def.h"
10 10
11#ifndef LUAJIT_USE_SYSMALLOC 11#ifndef LUAJIT_USE_SYSMALLOC
12LJ_FUNC void *lj_alloc_create(void); 12LJ_FUNC void *lj_alloc_create(PRNGState *rs);
13LJ_FUNC void lj_alloc_setprng(void *msp, PRNGState *rs);
13LJ_FUNC void lj_alloc_destroy(void *msp); 14LJ_FUNC void lj_alloc_destroy(void *msp);
14LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize); 15LJ_FUNC void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize);
15#endif 16#endif
diff --git a/src/lj_arch.h b/src/lj_arch.h
index 3e3581c2..626f6c13 100644
--- a/src/lj_arch.h
+++ b/src/lj_arch.h
@@ -633,4 +633,19 @@ extern void *LJ_WIN_LOADLIBA(const char *path);
633#define LJ_52 0 633#define LJ_52 0
634#endif 634#endif
635 635
636/* -- VM security --------------------------------------------------------- */
637
638/* Don't make any changes here. Instead build with:
639** make "XCFLAGS=-DLUAJIT_SECURITY_flag=value"
640*/
641
642/* Security defaults. */
643#ifndef LUAJIT_SECURITY_PRNG
644#define LUAJIT_SECURITY_PRNG 1
645#endif
646
647#ifndef LUAJIT_SECURITY_MCODE
648#define LUAJIT_SECURITY_MCODE 1
649#endif
650
636#endif 651#endif
diff --git a/src/lj_def.h b/src/lj_def.h
index af0687c4..e458c89f 100644
--- a/src/lj_def.h
+++ b/src/lj_def.h
@@ -372,4 +372,9 @@ static LJ_AINLINE uint32_t lj_getu32(const void *v)
372 extern void LJ_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1]) 372 extern void LJ_ASSERT_NAME(__LINE__)(int STATIC_ASSERTION_FAILED[(cond)?1:-1])
373#endif 373#endif
374 374
375/* PRNG state. Need this here, details in lj_prng.h. */
376typedef struct PRNGState {
377 uint64_t u[4];
378} PRNGState;
379
375#endif 380#endif
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c
index d34340ce..19da15a2 100644
--- a/src/lj_ffrecord.c
+++ b/src/lj_ffrecord.c
@@ -616,7 +616,7 @@ static void LJ_FASTCALL recff_math_random(jit_State *J, RecordFFData *rd)
616 GCudata *ud = udataV(&J->fn->c.upvalue[0]); 616 GCudata *ud = udataV(&J->fn->c.upvalue[0]);
617 TRef tr, one; 617 TRef tr, one;
618 lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */ 618 lj_ir_kgc(J, obj2gco(ud), IRT_UDATA); /* Prevent collection. */
619 tr = lj_ir_call(J, IRCALL_lj_math_random_step, lj_ir_kptr(J, uddata(ud))); 619 tr = lj_ir_call(J, IRCALL_lj_prng_u64d, lj_ir_kptr(J, uddata(ud)));
620 one = lj_ir_knum_one(J); 620 one = lj_ir_knum_one(J);
621 tr = emitir(IRTN(IR_SUB), tr, one); 621 tr = emitir(IRTN(IR_SUB), tr, one);
622 if (J->base[0]) { 622 if (J->base[0]) {
diff --git a/src/lj_ir.c b/src/lj_ir.c
index 600e432c..b5e94eb8 100644
--- a/src/lj_ir.c
+++ b/src/lj_ir.c
@@ -31,7 +31,7 @@
31#include "lj_vm.h" 31#include "lj_vm.h"
32#include "lj_strscan.h" 32#include "lj_strscan.h"
33#include "lj_strfmt.h" 33#include "lj_strfmt.h"
34#include "lj_lib.h" 34#include "lj_prng.h"
35 35
36/* Some local macros to save typing. Undef'd at the end. */ 36/* Some local macros to save typing. Undef'd at the end. */
37#define IR(ref) (&J->cur.ir[(ref)]) 37#define IR(ref) (&J->cur.ir[(ref)])
diff --git a/src/lj_ircall.h b/src/lj_ircall.h
index dbc8c0db..58cebc5d 100644
--- a/src/lj_ircall.h
+++ b/src/lj_ircall.h
@@ -172,7 +172,7 @@ typedef struct CCallInfo {
172 _(ANY, lj_gc_step_jit, 2, FS, NIL, CCI_L) \ 172 _(ANY, lj_gc_step_jit, 2, FS, NIL, CCI_L) \
173 _(ANY, lj_gc_barrieruv, 2, FS, NIL, 0) \ 173 _(ANY, lj_gc_barrieruv, 2, FS, NIL, 0) \
174 _(ANY, lj_mem_newgco, 2, FS, PGC, CCI_L) \ 174 _(ANY, lj_mem_newgco, 2, FS, PGC, CCI_L) \
175 _(ANY, lj_math_random_step, 1, FS, NUM, CCI_CASTU64) \ 175 _(ANY, lj_prng_u64d, 1, FS, NUM, CCI_CASTU64) \
176 _(ANY, lj_vm_modi, 2, FN, INT, 0) \ 176 _(ANY, lj_vm_modi, 2, FN, INT, 0) \
177 _(ANY, log10, 1, N, NUM, XA_FP) \ 177 _(ANY, log10, 1, N, NUM, XA_FP) \
178 _(ANY, exp, 1, N, NUM, XA_FP) \ 178 _(ANY, exp, 1, N, NUM, XA_FP) \
diff --git a/src/lj_jit.h b/src/lj_jit.h
index fa754b64..b0d90fcd 100644
--- a/src/lj_jit.h
+++ b/src/lj_jit.h
@@ -438,9 +438,9 @@ typedef struct jit_State {
438 int32_t framedepth; /* Current frame depth. */ 438 int32_t framedepth; /* Current frame depth. */
439 int32_t retdepth; /* Return frame depth (count of RETF). */ 439 int32_t retdepth; /* Return frame depth (count of RETF). */
440 440
441 uint32_t k32[LJ_K32__MAX]; /* Common 4 byte constants used by backends. */
441 TValue ksimd[LJ_KSIMD__MAX*2+1]; /* 16 byte aligned SIMD constants. */ 442 TValue ksimd[LJ_KSIMD__MAX*2+1]; /* 16 byte aligned SIMD constants. */
442 TValue k64[LJ_K64__MAX]; /* Common 8 byte constants used by backends. */ 443 TValue k64[LJ_K64__MAX]; /* Common 8 byte constants. */
443 uint32_t k32[LJ_K32__MAX]; /* Ditto for 4 byte constants. */
444 444
445 IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */ 445 IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */
446 IRRef irtoplim; /* Upper limit of instuction buffer (biased). */ 446 IRRef irtoplim; /* Upper limit of instuction buffer (biased). */
@@ -472,7 +472,6 @@ typedef struct jit_State {
472 472
473 HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */ 473 HotPenalty penalty[PENALTY_SLOTS]; /* Penalty slots. */
474 uint32_t penaltyslot; /* Round-robin index into penalty slots. */ 474 uint32_t penaltyslot; /* Round-robin index into penalty slots. */
475 uint32_t prngstate; /* PRNG state. */
476 475
477#ifdef LUAJIT_ENABLE_TABLE_BUMP 476#ifdef LUAJIT_ENABLE_TABLE_BUMP
478 RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */ 477 RBCHashEntry rbchash[RBCHASH_SLOTS]; /* Reverse bytecode map. */
@@ -516,12 +515,4 @@ jit_State;
516#define lj_assertJ(c, ...) ((void)J) 515#define lj_assertJ(c, ...) ((void)J)
517#endif 516#endif
518 517
519/* Trivial PRNG e.g. used for penalty randomization. */
520static LJ_AINLINE uint32_t LJ_PRNG_BITS(jit_State *J, int bits)
521{
522 /* Yes, this LCG is very weak, but that doesn't matter for our use case. */
523 J->prngstate = J->prngstate * 1103515245 + 12345;
524 return J->prngstate >> (32-bits);
525}
526
527#endif 518#endif
diff --git a/src/lj_lib.h b/src/lj_lib.h
index 83778b83..496bdb2a 100644
--- a/src/lj_lib.h
+++ b/src/lj_lib.h
@@ -107,9 +107,4 @@ LJ_FUNC int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id,
107#define LIBINIT_FFID 0xfe 107#define LIBINIT_FFID 0xfe
108#define LIBINIT_END 0xff 108#define LIBINIT_END 0xff
109 109
110/* Exported library functions. */
111
112typedef struct RandomState RandomState;
113LJ_FUNC uint64_t LJ_FASTCALL lj_math_random_step(RandomState *rs);
114
115#endif 110#endif
diff --git a/src/lj_mcode.c b/src/lj_mcode.c
index e64c5878..b2d12118 100644
--- a/src/lj_mcode.c
+++ b/src/lj_mcode.c
@@ -14,6 +14,7 @@
14#include "lj_mcode.h" 14#include "lj_mcode.h"
15#include "lj_trace.h" 15#include "lj_trace.h"
16#include "lj_dispatch.h" 16#include "lj_dispatch.h"
17#include "lj_prng.h"
17#endif 18#endif
18#if LJ_HASJIT || LJ_HASFFI 19#if LJ_HASJIT || LJ_HASFFI
19#include "lj_vm.h" 20#include "lj_vm.h"
@@ -118,52 +119,34 @@ static int mcode_setprot(void *p, size_t sz, int prot)
118 return mprotect(p, sz, prot); 119 return mprotect(p, sz, prot);
119} 120}
120 121
121#elif LJ_64
122
123#error "Missing OS support for explicit placement of executable memory"
124
125#else 122#else
126 123
127/* Fallback allocator. This will fail if memory is not executable by default. */ 124#error "Missing OS support for explicit placement of executable memory"
128#define LUAJIT_UNPROTECT_MCODE
129#define MCPROT_RW 0
130#define MCPROT_RX 0
131#define MCPROT_RWX 0
132
133static void *mcode_alloc_at(jit_State *J, uintptr_t hint, size_t sz, int prot)
134{
135 UNUSED(hint); UNUSED(prot);
136 return lj_mem_new(J->L, sz);
137}
138
139static void mcode_free(jit_State *J, void *p, size_t sz)
140{
141 lj_mem_free(J2G(J), p, sz);
142}
143 125
144#endif 126#endif
145 127
146/* -- MCode area protection ----------------------------------------------- */ 128/* -- MCode area protection ----------------------------------------------- */
147 129
148/* Define this ONLY if page protection twiddling becomes a bottleneck. */ 130#if LUAJIT_SECURITY_MCODE == 0
149#ifdef LUAJIT_UNPROTECT_MCODE
150 131
151/* It's generally considered to be a potential security risk to have 132/* Define this ONLY if page protection twiddling becomes a bottleneck.
133**
134** It's generally considered to be a potential security risk to have
152** pages with simultaneous write *and* execute access in a process. 135** pages with simultaneous write *and* execute access in a process.
153** 136**
154** Do not even think about using this mode for server processes or 137** Do not even think about using this mode for server processes or
155** apps handling untrusted external data (such as a browser). 138** apps handling untrusted external data.
156** 139**
157** The security risk is not in LuaJIT itself -- but if an adversary finds 140** The security risk is not in LuaJIT itself -- but if an adversary finds
158** any *other* flaw in your C application logic, then any RWX memory page 141** any *other* flaw in your C application logic, then any RWX memory pages
159** simplifies writing an exploit considerably. 142** simplify writing an exploit considerably.
160*/ 143*/
161#define MCPROT_GEN MCPROT_RWX 144#define MCPROT_GEN MCPROT_RWX
162#define MCPROT_RUN MCPROT_RWX 145#define MCPROT_RUN MCPROT_RWX
163 146
164static void mcode_protect(jit_State *J, int prot) 147static void mcode_protect(jit_State *J, int prot)
165{ 148{
166 UNUSED(J); UNUSED(prot); 149 UNUSED(J); UNUSED(prot); UNUSED(mcode_setprot);
167} 150}
168 151
169#else 152#else
@@ -242,7 +225,7 @@ static void *mcode_alloc(jit_State *J, size_t sz)
242 } 225 }
243 /* Next try probing 64K-aligned pseudo-random addresses. */ 226 /* Next try probing 64K-aligned pseudo-random addresses. */
244 do { 227 do {
245 hint = LJ_PRNG_BITS(J, LJ_TARGET_JUMPRANGE-16) << 16; 228 hint = lj_prng_u64(&J2G(J)->prng) & ((1u<<LJ_TARGET_JUMPRANGE)-0x10000);
246 } while (!(hint + sz < range+range)); 229 } while (!(hint + sz < range+range));
247 hint = target + hint - range; 230 hint = target + hint - range;
248 } 231 }
@@ -331,7 +314,7 @@ void lj_mcode_abort(jit_State *J)
331/* Set/reset protection to allow patching of MCode areas. */ 314/* Set/reset protection to allow patching of MCode areas. */
332MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish) 315MCode *lj_mcode_patch(jit_State *J, MCode *ptr, int finish)
333{ 316{
334#ifdef LUAJIT_UNPROTECT_MCODE 317#if LUAJIT_SECURITY_MCODE == 0
335 UNUSED(J); UNUSED(ptr); UNUSED(finish); 318 UNUSED(J); UNUSED(ptr); UNUSED(finish);
336 return NULL; 319 return NULL;
337#else 320#else
diff --git a/src/lj_obj.h b/src/lj_obj.h
index c0ae6892..6c974812 100644
--- a/src/lj_obj.h
+++ b/src/lj_obj.h
@@ -620,6 +620,7 @@ typedef struct global_State {
620 GCRef cur_L; /* Currently executing lua_State. */ 620 GCRef cur_L; /* Currently executing lua_State. */
621 MRef jit_base; /* Current JIT code L->base or NULL. */ 621 MRef jit_base; /* Current JIT code L->base or NULL. */
622 MRef ctype_state; /* Pointer to C type state. */ 622 MRef ctype_state; /* Pointer to C type state. */
623 PRNGState prng; /* Global PRNG state. */
623 GCRef gcroot[GCROOT_MAX]; /* GC roots. */ 624 GCRef gcroot[GCROOT_MAX]; /* GC roots. */
624} global_State; 625} global_State;
625 626
diff --git a/src/lj_prng.c b/src/lj_prng.c
new file mode 100644
index 00000000..62a6bbb7
--- /dev/null
+++ b/src/lj_prng.c
@@ -0,0 +1,225 @@
1/*
2** Pseudo-random number generation.
3** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#define lj_prng_c
7#define LUA_CORE
8
9/* To get the syscall prototype. */
10#if defined(__linux__) && !defined(_GNU_SOURCE)
11#define _GNU_SOURCE
12#endif
13
14#include "lj_def.h"
15#include "lj_arch.h"
16#include "lj_prng.h"
17
18/* -- PRNG step function -------------------------------------------------- */
19
20/* This implements a Tausworthe PRNG with period 2^223. Based on:
21** Tables of maximally-equidistributed combined LFSR generators,
22** Pierre L'Ecuyer, 1991, table 3, 1st entry.
23** Full-period ME-CF generator with L=64, J=4, k=223, N1=49.
24**
25** Important note: This PRNG is NOT suitable for cryptographic use!
26**
27** But it works fine for math.random(), which has an API that's not
28** suitable for cryptography, anyway.
29**
30** When used as a securely seeded global PRNG, it substantially raises
31** the difficulty for various attacks on the VM.
32*/
33
34/* Update generator i and compute a running xor of all states. */
35#define TW223_GEN(rs, z, r, i, k, q, s) \
36 z = rs->u[i]; \
37 z = (((z<<q)^z) >> (k-s)) ^ ((z&((uint64_t)(int64_t)-1 << (64-k)))<<s); \
38 r ^= z; rs->u[i] = z;
39
40#define TW223_STEP(rs, z, r) \
41 TW223_GEN(rs, z, r, 0, 63, 31, 18) \
42 TW223_GEN(rs, z, r, 1, 58, 19, 28) \
43 TW223_GEN(rs, z, r, 2, 55, 24, 7) \
44 TW223_GEN(rs, z, r, 3, 47, 21, 8)
45
46/* PRNG step function with uint64_t result. */
47LJ_NOINLINE uint64_t LJ_FASTCALL lj_prng_u64(PRNGState *rs)
48{
49 uint64_t z, r = 0;
50 TW223_STEP(rs, z, r)
51 return r;
52}
53
54/* PRNG step function with double in uint64_t result. */
55LJ_NOINLINE uint64_t LJ_FASTCALL lj_prng_u64d(PRNGState *rs)
56{
57 uint64_t z, r = 0;
58 TW223_STEP(rs, z, r)
59 /* Returns a double bit pattern in the range 1.0 <= d < 2.0. */
60 return (r & U64x(000fffff,ffffffff)) | U64x(3ff00000,00000000);
61}
62
63/* Condition seed: ensure k[i] MSB of u[i] are non-zero. */
64static LJ_AINLINE void lj_prng_condition(PRNGState *rs)
65{
66 if (rs->u[0] < (1u << 1)) rs->u[0] += (1u << 1);
67 if (rs->u[1] < (1u << 6)) rs->u[1] += (1u << 6);
68 if (rs->u[2] < (1u << 9)) rs->u[2] += (1u << 9);
69 if (rs->u[3] < (1u << 17)) rs->u[3] += (1u << 17);
70}
71
72/* -- PRNG seeding from OS ------------------------------------------------ */
73
74#if LUAJIT_SECURITY_PRNG == 0
75
76/* Nothing to define. */
77
78#elif LJ_TARGET_XBOX360
79
80extern int XNetRandom(void *buf, unsigned int len);
81
82#elif LJ_TARGET_PS3
83
84extern int sys_get_random_number(void *buf, uint64_t len);
85
86#elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA
87
88extern int sceRandomGetRandomNumber(void *buf, size_t len);
89
90#elif LJ_TARGET_WINDOWS || LJ_TARGET_XBOXONE
91
92#define WIN32_LEAN_AND_MEAN
93#include <windows.h>
94
95#if LJ_TARGET_UWP || LJ_TARGET_XBOXONE
96/* Must use BCryptGenRandom. */
97#include <bcrypt.h>
98#pragma comment(lib, "bcrypt.lib")
99#else
100/* If you wonder about this mess, then search online for RtlGenRandom. */
101typedef BOOLEAN (WINAPI *PRGR)(void *buf, ULONG len);
102static PRGR libfunc_rgr;
103#endif
104
105#elif LJ_TARGET_POSIX
106
107#if LJ_TARGET_LINUX
108/* Avoid a dependency on glibc 2.25+ and use the getrandom syscall instead. */
109#include <sys/syscall.h>
110#elif LJ_TARGET_OSX || LJ_TARGET_BSD || LJ_TARGET_SOLARIS || LJ_TARGET_CYGWIN
111extern int getentropy(void *buf, size_t len);
112#ifdef __ELF__
113 __attribute__((weak))
114#endif
115;
116#endif
117
118/* For the /dev/urandom fallback. */
119#include <fcntl.h>
120#include <unistd.h>
121
122#endif
123
124#if LUAJIT_SECURITY_PRNG == 0
125
126/* If you really don't care about security, then define
127** LUAJIT_SECURITY_PRNG=0. This yields a predictable seed
128** and provides NO SECURITY against various attacks on the VM.
129**
130** BTW: This is NOT the way to get predictable table iteration,
131** predictable trace generation, predictable bytecode generation, etc.
132*/
133int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs)
134{
135 lj_prng_seed_fixed(rs); /* The fixed seed is already conditioned. */
136 return 1;
137}
138
139#else
140
141/* Securely seed PRNG from system entropy. Returns 0 on failure. */
142int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs)
143{
144#if LJ_TARGET_XBOX360
145
146 if (XNetRandom(rs->u, (unsigned int)sizeof(rs->u)) == 0)
147 goto ok;
148
149#elif LJ_TARGET_PS3
150
151 if (sys_get_random_number(rs->u, sizeof(rs->u)) == 0)
152 goto ok;
153
154#elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA
155
156 if (sceRandomGetRandomNumber(rs->u, sizeof(rs->u) == 0)
157 goto ok;
158
159#elif LJ_TARGET_UWP || LJ_TARGET_XBOXONE
160
161 if (BCryptGenRandom(NULL, (PUCHAR)(rs->u), (ULONG)sizeof(rs->u),
162 BCRYPT_USE_SYSTEM_PREFERRED_RNG) >= 0)
163 goto ok;
164
165#elif LJ_TARGET_WINDOWS
166
167 /* Keep the library loaded in case multiple VMs are started. */
168 if (!libfunc_rgr) {
169 HMODULE lib = LJ_WIN_LOADLIBA("advapi32.dll");
170 if (!lib) return 0;
171 libfunc_rgr = (PRGR)GetProcAddress(lib, "SystemFunction036");
172 if (!libfunc_rgr) return 0;
173 }
174 if (libfunc_rgr(rs->u, (ULONG)sizeof(rs->u)))
175 goto ok;
176
177#elif LJ_TARGET_POSIX
178
179#if LJ_TARGET_LINUX && defined(SYS_getrandom)
180
181 if (syscall(SYS_getrandom, rs->u, sizeof(rs->u), 0) == (long)sizeof(rs->u))
182 goto ok;
183
184#elif LJ_TARGET_OSX || LJ_TARGET_BSD || LJ_TARGET_SOLARIS || LJ_TARGET_CYGWIN
185
186 if ((!__ELF__ || getentropy) && getentropy(rs->u, sizeof(rs->u)) == 0)
187 goto ok;
188
189#endif
190
191 /* Fallback to /dev/urandom. This may fail if the device is not
192 ** existent or accessible in a chroot or container, or if the process
193 ** or the OS ran out of file descriptors.
194 */
195 {
196 int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC);
197 if (fd != -1) {
198 ssize_t n = read(fd, rs->u, sizeof(rs->u));
199 (void)close(fd);
200 if (n == (ssize_t)sizeof(rs->u))
201 goto ok;
202 }
203 }
204
205#else
206
207 /* Add an elif above for your OS with a secure PRNG seed.
208 ** Note that fiddling around with rand(), getpid(), time() or coercing
209 ** ASLR to yield a few bits of randomness is not helpful.
210 ** If you don't want any security, then don't pretend you have any
211 ** and simply define LUAJIT_SECURITY_PRNG=0 for the build.
212 */
213#error "Missing secure PRNG seed for this OS"
214
215#endif
216 return 0; /* Fail. */
217
218ok:
219 lj_prng_condition(rs);
220 (void)lj_prng_u64(rs);
221 return 1; /* Success. */
222}
223
224#endif
225
diff --git a/src/lj_prng.h b/src/lj_prng.h
new file mode 100644
index 00000000..40c34a71
--- /dev/null
+++ b/src/lj_prng.h
@@ -0,0 +1,24 @@
1/*
2** Pseudo-random number generation.
3** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#ifndef _LJ_PRNG_H
7#define _LJ_PRNG_H
8
9#include "lj_def.h"
10
11LJ_FUNC int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs);
12LJ_FUNC uint64_t LJ_FASTCALL lj_prng_u64(PRNGState *rs);
13LJ_FUNC uint64_t LJ_FASTCALL lj_prng_u64d(PRNGState *rs);
14
15/* This is just the precomputed result of lib_math.c:random_seed(rs, 0.0). */
16static LJ_AINLINE void lj_prng_seed_fixed(PRNGState *rs)
17{
18 rs->u[0] = U64x(a0d27757,0a345b8c);
19 rs->u[1] = U64x(764a296c,5d4aa64f);
20 rs->u[2] = U64x(51220704,070adeaa);
21 rs->u[3] = U64x(2a2717b5,a7b7b927);
22}
23
24#endif
diff --git a/src/lj_record.c b/src/lj_record.c
index cfa48ecf..df428818 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -33,6 +33,7 @@
33#include "lj_snap.h" 33#include "lj_snap.h"
34#include "lj_dispatch.h" 34#include "lj_dispatch.h"
35#include "lj_vm.h" 35#include "lj_vm.h"
36#include "lj_prng.h"
36 37
37/* Some local macros to save typing. Undef'd at the end. */ 38/* Some local macros to save typing. Undef'd at the end. */
38#define IR(ref) (&J->cur.ir[(ref)]) 39#define IR(ref) (&J->cur.ir[(ref)])
@@ -1696,7 +1697,7 @@ static void check_call_unroll(jit_State *J, TraceNo lnk)
1696 if (lnk) { /* Possible tail- or up-recursion. */ 1697 if (lnk) { /* Possible tail- or up-recursion. */
1697 lj_trace_flush(J, lnk); /* Flush trace that only returns. */ 1698 lj_trace_flush(J, lnk); /* Flush trace that only returns. */
1698 /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */ 1699 /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */
1699 hotcount_set(J2GG(J), J->pc+1, LJ_PRNG_BITS(J, 4)); 1700 hotcount_set(J2GG(J), J->pc+1, lj_prng_u64(&J2G(J)->prng) & 15u);
1700 } 1701 }
1701 lj_trace_err(J, LJ_TRERR_CUNROLL); 1702 lj_trace_err(J, LJ_TRERR_CUNROLL);
1702 } 1703 }
diff --git a/src/lj_state.c b/src/lj_state.c
index 7081a474..a4d072be 100644
--- a/src/lj_state.c
+++ b/src/lj_state.c
@@ -25,6 +25,7 @@
25#include "lj_trace.h" 25#include "lj_trace.h"
26#include "lj_dispatch.h" 26#include "lj_dispatch.h"
27#include "lj_vm.h" 27#include "lj_vm.h"
28#include "lj_prng.h"
28#include "lj_lex.h" 29#include "lj_lex.h"
29#include "lj_alloc.h" 30#include "lj_alloc.h"
30#include "luajit.h" 31#include "luajit.h"
@@ -185,16 +186,33 @@ static void close_state(lua_State *L)
185} 186}
186 187
187#if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC)) 188#if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC))
188lua_State *lj_state_newstate(lua_Alloc f, void *ud) 189lua_State *lj_state_newstate(lua_Alloc allocf, void *allocd)
189#else 190#else
190LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) 191LUA_API lua_State *lua_newstate(lua_Alloc allocf, void *allocd)
191#endif 192#endif
192{ 193{
193 GG_State *GG = (GG_State *)f(ud, NULL, 0, sizeof(GG_State)); 194 PRNGState prng;
194 lua_State *L = &GG->L; 195 GG_State *GG;
195 global_State *g = &GG->g; 196 lua_State *L;
197 global_State *g;
198 /* We need the PRNG for the memory allocator, so initialize this first. */
199 if (!lj_prng_seed_secure(&prng)) {
200 lj_assertX(0, "secure PRNG seeding failed");
201 /* Can only return NULL here, so this errors with "not enough memory". */
202 return NULL;
203 }
204#ifndef LUAJIT_USE_SYSMALLOC
205 if (allocf == LJ_ALLOCF_INTERNAL) {
206 allocd = lj_alloc_create(&prng);
207 if (!allocd) return NULL;
208 allocf = lj_alloc_f;
209 }
210#endif
211 GG = (GG_State *)allocf(allocd, NULL, 0, sizeof(GG_State));
196 if (GG == NULL || !checkptrGC(GG)) return NULL; 212 if (GG == NULL || !checkptrGC(GG)) return NULL;
197 memset(GG, 0, sizeof(GG_State)); 213 memset(GG, 0, sizeof(GG_State));
214 L = &GG->L;
215 g = &GG->g;
198 L->gct = ~LJ_TTHREAD; 216 L->gct = ~LJ_TTHREAD;
199 L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */ 217 L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */
200 L->dummy_ffid = FF_C; 218 L->dummy_ffid = FF_C;
@@ -202,8 +220,14 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
202 g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED; 220 g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED;
203 g->strempty.marked = LJ_GC_WHITE0; 221 g->strempty.marked = LJ_GC_WHITE0;
204 g->strempty.gct = ~LJ_TSTR; 222 g->strempty.gct = ~LJ_TSTR;
205 g->allocf = f; 223 g->allocf = allocf;
206 g->allocd = ud; 224 g->allocd = allocd;
225 g->prng = prng;
226#ifndef LUAJIT_USE_SYSMALLOC
227 if (allocf == lj_alloc_f) {
228 lj_alloc_setprng(allocd, &g->prng);
229 }
230#endif
207 setgcref(g->mainthref, obj2gco(L)); 231 setgcref(g->mainthref, obj2gco(L));
208 setgcref(g->uvhead.prev, obj2gco(&g->uvhead)); 232 setgcref(g->uvhead.prev, obj2gco(&g->uvhead));
209 setgcref(g->uvhead.next, obj2gco(&g->uvhead)); 233 setgcref(g->uvhead.next, obj2gco(&g->uvhead));
diff --git a/src/lj_state.h b/src/lj_state.h
index 9a8c7d93..50fe9000 100644
--- a/src/lj_state.h
+++ b/src/lj_state.h
@@ -32,4 +32,6 @@ LJ_FUNC void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L);
32LJ_FUNC lua_State *lj_state_newstate(lua_Alloc f, void *ud); 32LJ_FUNC lua_State *lj_state_newstate(lua_Alloc f, void *ud);
33#endif 33#endif
34 34
35#define LJ_ALLOCF_INTERNAL ((lua_Alloc)(void *)(uintptr_t)(1237<<4))
36
35#endif 37#endif
diff --git a/src/lj_trace.c b/src/lj_trace.c
index c4e728c6..77e9d05b 100644
--- a/src/lj_trace.c
+++ b/src/lj_trace.c
@@ -30,6 +30,7 @@
30#include "lj_vm.h" 30#include "lj_vm.h"
31#include "lj_vmevent.h" 31#include "lj_vmevent.h"
32#include "lj_target.h" 32#include "lj_target.h"
33#include "lj_prng.h"
33 34
34/* -- Error handling ------------------------------------------------------ */ 35/* -- Error handling ------------------------------------------------------ */
35 36
@@ -384,7 +385,7 @@ static void penalty_pc(jit_State *J, GCproto *pt, BCIns *pc, TraceError e)
384 if (mref(J->penalty[i].pc, const BCIns) == pc) { /* Cache slot found? */ 385 if (mref(J->penalty[i].pc, const BCIns) == pc) { /* Cache slot found? */
385 /* First try to bump its hotcount several times. */ 386 /* First try to bump its hotcount several times. */
386 val = ((uint32_t)J->penalty[i].val << 1) + 387 val = ((uint32_t)J->penalty[i].val << 1) +
387 LJ_PRNG_BITS(J, PENALTY_RNDBITS); 388 (lj_prng_u64(&J2G(J)->prng) & ((1u<<PENALTY_RNDBITS)-1));
388 if (val > PENALTY_MAX) { 389 if (val > PENALTY_MAX) {
389 blacklist_pc(pt, pc); /* Blacklist it, if that didn't help. */ 390 blacklist_pc(pt, pc); /* Blacklist it, if that didn't help. */
390 return; 391 return;
diff --git a/src/ljamalg.c b/src/ljamalg.c
index 19980241..56585e6d 100644
--- a/src/ljamalg.c
+++ b/src/ljamalg.c
@@ -31,6 +31,7 @@
31#include "lj_udata.c" 31#include "lj_udata.c"
32#include "lj_meta.c" 32#include "lj_meta.c"
33#include "lj_debug.c" 33#include "lj_debug.c"
34#include "lj_prng.c"
34#include "lj_state.c" 35#include "lj_state.c"
35#include "lj_dispatch.c" 36#include "lj_dispatch.c"
36#include "lj_vmevent.c" 37#include "lj_vmevent.c"