Experimental optimization to skip oom check

This commit is contained in:
Alex Orlenko 2022-05-29 21:52:50 +01:00
parent 99becdb590
commit 3766cee4dd
No known key found for this signature in database
GPG Key ID: 4C150C250863B96D
2 changed files with 100 additions and 27 deletions

View File

@ -1423,7 +1423,13 @@ impl Lua {
unsafe { unsafe {
let _sg = StackGuard::new(self.state); let _sg = StackGuard::new(self.state);
check_stack(self.state, 3)?; check_stack(self.state, 3)?;
push_string(self.state, s)?;
if self.unlikely_memory_error() {
let s = s.as_ref();
ffi::lua_pushlstring(self.state, s.as_ptr() as *const c_char, s.len());
} else {
push_string(self.state, s)?;
}
Ok(String(self.pop_ref())) Ok(String(self.pop_ref()))
} }
} }
@ -1433,7 +1439,12 @@ impl Lua {
unsafe { unsafe {
let _sg = StackGuard::new(self.state); let _sg = StackGuard::new(self.state);
check_stack(self.state, 2)?; check_stack(self.state, 2)?;
protect_lua!(self.state, 0, 1, fn(state) ffi::lua_newtable(state))?;
if self.unlikely_memory_error() {
ffi::lua_newtable(self.state);
} else {
protect_lua!(self.state, 0, 1, fn(state) ffi::lua_newtable(state))?;
}
Ok(Table(self.pop_ref())) Ok(Table(self.pop_ref()))
} }
} }
@ -1446,7 +1457,13 @@ impl Lua {
unsafe { unsafe {
let _sg = StackGuard::new(self.state); let _sg = StackGuard::new(self.state);
check_stack(self.state, 3)?; check_stack(self.state, 3)?;
push_table(self.state, narr, nrec)?;
if self.unlikely_memory_error() {
ffi::lua_createtable(self.state, narr, nrec);
} else {
push_table(self.state, narr, nrec)?;
}
Ok(Table(self.pop_ref())) Ok(Table(self.pop_ref()))
} }
} }
@ -1464,11 +1481,21 @@ impl Lua {
let iter = iter.into_iter(); let iter = iter.into_iter();
let lower_bound = iter.size_hint().0; let lower_bound = iter.size_hint().0;
push_table(self.state, 0, lower_bound as c_int)?;
for (k, v) in iter { if self.unlikely_memory_error() {
self.push_value(k.to_lua(self)?)?; ffi::lua_createtable(self.state, 0, lower_bound as c_int);
self.push_value(v.to_lua(self)?)?; for (k, v) in iter {
protect_lua!(self.state, 3, 1, fn(state) ffi::lua_rawset(state, -3))?; self.push_value(k.to_lua(self)?)?;
self.push_value(v.to_lua(self)?)?;
ffi::lua_rawset(self.state, -3);
}
} else {
push_table(self.state, 0, lower_bound as c_int)?;
for (k, v) in iter {
self.push_value(k.to_lua(self)?)?;
self.push_value(v.to_lua(self)?)?;
protect_lua!(self.state, 3, 1, fn(state) ffi::lua_rawset(state, -3))?;
}
} }
Ok(Table(self.pop_ref())) Ok(Table(self.pop_ref()))
@ -1487,12 +1514,21 @@ impl Lua {
let iter = iter.into_iter(); let iter = iter.into_iter();
let lower_bound = iter.size_hint().0; let lower_bound = iter.size_hint().0;
push_table(self.state, lower_bound as c_int, 0)?;
for (i, v) in iter.enumerate() { if self.unlikely_memory_error() {
self.push_value(v.to_lua(self)?)?; ffi::lua_createtable(self.state, lower_bound as c_int, 0);
protect_lua!(self.state, 2, 1, |state| { for (i, v) in iter.enumerate() {
ffi::lua_rawseti(state, -2, (i + 1) as Integer); self.push_value(v.to_lua(self)?)?;
})?; ffi::lua_rawseti(self.state, -2, (i + 1) as Integer);
}
} else {
push_table(self.state, lower_bound as c_int, 0)?;
for (i, v) in iter.enumerate() {
self.push_value(v.to_lua(self)?)?;
protect_lua!(self.state, 2, 1, |state| {
ffi::lua_rawseti(state, -2, (i + 1) as Integer);
})?;
}
} }
Ok(Table(self.pop_ref())) Ok(Table(self.pop_ref()))
@ -1651,7 +1687,11 @@ impl Lua {
let _sg = StackGuard::new(self.state); let _sg = StackGuard::new(self.state);
check_stack(self.state, 3)?; check_stack(self.state, 3)?;
let thread_state = protect_lua!(self.state, 0, 1, |state| ffi::lua_newthread(state))?; let thread_state = if self.unlikely_memory_error() {
ffi::lua_newthread(self.state)
} else {
protect_lua!(self.state, 0, 1, |state| ffi::lua_newthread(state))?
};
self.push_ref(&func.0); self.push_ref(&func.0);
ffi::lua_xmove(self.state, thread_state, 1); ffi::lua_xmove(self.state, thread_state, 1);
@ -1826,9 +1866,13 @@ impl Lua {
check_stack(self.state, 4)?; check_stack(self.state, 4)?;
self.push_value(v)?; self.push_value(v)?;
let res = protect_lua!(self.state, 1, 1, |state| { let res = if self.unlikely_memory_error() {
ffi::lua_tolstring(state, -1, ptr::null_mut()) ffi::lua_tolstring(self.state, -1, ptr::null_mut())
})?; } else {
protect_lua!(self.state, 1, 1, |state| {
ffi::lua_tolstring(state, -1, ptr::null_mut())
})?
};
if !res.is_null() { if !res.is_null() {
Some(String(self.pop_ref())) Some(String(self.pop_ref()))
} else { } else {
@ -2582,9 +2626,13 @@ impl Lua {
let func = mem::transmute(func); let func = mem::transmute(func);
let extra = Arc::clone(&self.extra); let extra = Arc::clone(&self.extra);
push_gc_userdata(self.state, CallbackUpvalue { data: func, extra })?; push_gc_userdata(self.state, CallbackUpvalue { data: func, extra })?;
protect_lua!(self.state, 1, 1, fn(state) { if self.unlikely_memory_error() {
ffi::lua_pushcclosure(state, call_callback, 1); ffi::lua_pushcclosure(self.state, call_callback, 1);
})?; } else {
protect_lua!(self.state, 1, 1, fn(state) {
ffi::lua_pushcclosure(state, call_callback, 1);
})?;
}
Ok(Function(self.pop_ref())) Ok(Function(self.pop_ref()))
} }
@ -2641,9 +2689,13 @@ impl Lua {
let fut = func(lua, args); let fut = func(lua, args);
let extra = Arc::clone(&(*upvalue).extra); let extra = Arc::clone(&(*upvalue).extra);
push_gc_userdata(state, AsyncPollUpvalue { data: fut, extra })?; push_gc_userdata(state, AsyncPollUpvalue { data: fut, extra })?;
protect_lua!(state, 1, 1, fn(state) { if lua.unlikely_memory_error() {
ffi::lua_pushcclosure(state, poll_future, 1); ffi::lua_pushcclosure(state, poll_future, 1);
})?; } else {
protect_lua!(state, 1, 1, fn(state) {
ffi::lua_pushcclosure(state, poll_future, 1);
})?;
}
Ok(1) Ok(1)
}) })
@ -2703,9 +2755,13 @@ impl Lua {
let func = mem::transmute(func); let func = mem::transmute(func);
let extra = Arc::clone(&self.extra); let extra = Arc::clone(&self.extra);
push_gc_userdata(self.state, AsyncCallbackUpvalue { data: func, extra })?; push_gc_userdata(self.state, AsyncCallbackUpvalue { data: func, extra })?;
protect_lua!(self.state, 1, 1, fn(state) { if self.unlikely_memory_error() {
ffi::lua_pushcclosure(state, call_callback, 1); ffi::lua_pushcclosure(self.state, call_callback, 1);
})?; } else {
protect_lua!(self.state, 1, 1, fn(state) {
ffi::lua_pushcclosure(state, call_callback, 1);
})?;
}
Function(self.pop_ref()) Function(self.pop_ref())
}; };
@ -2849,6 +2905,17 @@ impl Lua {
} }
} }
} }
#[inline]
pub(crate) unsafe fn unlikely_memory_error(&self) -> bool {
let extra = &mut *self.extra.get();
cfg!(target_os = "linux")
&& cfg!(not(feature = "module"))
&& extra
.mem_info
.map(|x| x.as_ref().memory_limit == 0)
.unwrap_or(true)
}
} }
struct StateGuard<'a>(&'a mut LuaInner, *mut ffi::lua_State); struct StateGuard<'a>(&'a mut LuaInner, *mut ffi::lua_State);

View File

@ -198,7 +198,13 @@ impl<'lua> Table<'lua> {
lua.push_ref(&self.0); lua.push_ref(&self.0);
lua.push_value(key)?; lua.push_value(key)?;
lua.push_value(value)?; lua.push_value(value)?;
protect_lua!(lua.state, 3, 0, fn(state) ffi::lua_rawset(state, -3)) if lua.unlikely_memory_error() {
ffi::lua_rawset(lua.state, -3);
ffi::lua_pop(lua.state, 1);
Ok(())
} else {
protect_lua!(lua.state, 3, 0, fn(state) ffi::lua_rawset(state, -3))
}
} }
} }