use raw allocator for creating strings

This commit is contained in:
Robin Appelman 2019-04-06 14:03:09 +02:00
commit 71b8b56454

View file

@ -1,8 +1,9 @@
use std::alloc::{alloc, Layout};
use std::fmt; use std::fmt;
use std::fmt::Display; use std::fmt::Display;
use std::intrinsics::transmute; use std::intrinsics::transmute;
use std::mem::{forget, size_of}; use std::mem::size_of;
use std::str; use std::{ptr, str};
use ivory_sys::*; use ivory_sys::*;
@ -18,8 +19,8 @@ impl ExecuteData {
fn get_arg_base(&self) -> *const ZVal { fn get_arg_base(&self) -> *const ZVal {
let offset = (size_of::<zend_execute_data>() + size_of::<zval>() - 1) / size_of::<zval>(); let offset = (size_of::<zend_execute_data>() + size_of::<zval>() - 1) / size_of::<zval>();
let self_ptr: *const zend_execute_data = &self.0; let self_ptr = (&self.0 as *const zend_execute_data) as *const ZVal;
unsafe { transmute::<_, *const ZVal>(self_ptr).add(offset) } unsafe { self_ptr.add(offset) }
} }
pub unsafe fn get_arg(&self, i: u32) -> &ZVal { pub unsafe fn get_arg(&self, i: u32) -> &ZVal {
@ -59,7 +60,7 @@ impl Iterator for IntoArgIterator {
unsafe fn zend_str_as_string(string: *const zend_string) -> String { unsafe fn zend_str_as_string(string: *const zend_string) -> String {
let len = (*string).len; let len = (*string).len;
let base: *const u8 = transmute(string); let base = string as *const u8;
let str_start = base.add(size_of::<ZendStringHeader>()); let str_start = base.add(size_of::<ZendStringHeader>());
let slice: &[u8] = std::slice::from_raw_parts(str_start, len); let slice: &[u8] = std::slice::from_raw_parts(str_start, len);
@ -76,7 +77,11 @@ pub struct ZendStringHeader {
fn string_into_zend_str(string: String) -> *mut zend_string { fn string_into_zend_str(string: String) -> *mut zend_string {
let len = string.len(); let len = string.len();
let mut mem: Vec<u8> = Vec::with_capacity(len + size_of::<ZendStringHeader>()); let header_size = size_of::<ZendStringHeader>();
let layout = Layout::from_size_align(len + header_size, size_of::<zend_string>())
.expect("invalid layout");
let raw = unsafe { alloc(layout) };
let header = ZendStringHeader { let header = ZendStringHeader {
gc: zend_refcounted_h { gc: zend_refcounted_h {
@ -86,22 +91,12 @@ fn string_into_zend_str(string: String) -> *mut zend_string {
h: 0, h: 0,
len, len,
}; };
let header_bytes: [u8; size_of::<ZendStringHeader>()] = unsafe { transmute(header) }; unsafe {
mem.extend_from_slice(&header_bytes); ptr::write(raw as *mut ZendStringHeader, header);
ptr::copy(string.as_ptr(), raw.add(header_size), len);
};
let bytes = string.into_bytes(); raw as *mut zend_string
mem.extend_from_slice(bytes.as_slice());
let ptr = mem.as_ptr();
// rust shouldn't deallocate the data
// this isn't perfect since all the extra vec bits (length, capacity)
// will be leaked
// maybe this should be copied instead
forget(mem);
unsafe { transmute(ptr) }
} }
#[repr(transparent)] #[repr(transparent)]