0
0
Fork 0
mirror of https://github.com/denoland/rusty_v8.git synced 2024-12-24 08:09:16 -05:00

Work towards creating first Isolate (#12)

This commit is contained in:
Bert Belder 2019-11-15 16:21:34 -08:00
parent 643e1956a1
commit 37a656014b
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
18 changed files with 356 additions and 151 deletions

5
.gitignore vendored
View file

@ -1,5 +1,8 @@
/target
**/*.rs.bk **/*.rs.bk
**/*.orig
/.vscode/
/target/
/third_party/.cipd/ /third_party/.cipd/
/third_party/gclient_config.py_entries /third_party/gclient_config.py_entries
/third_party/v8/ /third_party/v8/

125
.vscode/settings.json vendored
View file

@ -1,125 +0,0 @@
{
"C_Cpp.clang_format_style": "Chromium",
"files.associations": {
"memory": "cpp",
"vector": "cpp",
"cctype": "cpp",
"algorithm": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"bitset": "cpp",
"cfenv": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"cinttypes": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"complex": "cpp",
"condition_variable": "cpp",
"csetjmp": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cuchar": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"forward_list": "cpp",
"fstream": "cpp",
"functional": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"map": "cpp",
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
"optional": "cpp",
"ostream": "cpp",
"queue": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"scoped_allocator": "cpp",
"set": "cpp",
"shared_mutex": "cpp",
"sstream": "cpp",
"stack": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"string_view": "cpp",
"strstream": "cpp",
"system_error": "cpp",
"xthread": "cpp",
"thread": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"utility": "cpp",
"valarray": "cpp",
"variant": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xmemory0": "cpp",
"xstddef": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp",
"__bit_reference": "cpp",
"__config": "cpp",
"__debug": "cpp",
"__errc": "cpp",
"__functional_base": "cpp",
"__hash_table": "cpp",
"__locale": "cpp",
"__mutex_base": "cpp",
"__node_handle": "cpp",
"__nullptr": "cpp",
"__split_buffer": "cpp",
"__sso_allocator": "cpp",
"__std_stream": "cpp",
"__string": "cpp",
"__threading_support": "cpp",
"__tree": "cpp",
"__tuple": "cpp",
"bit": "cpp",
"compare": "cpp",
"coroutine": "cpp",
"propagate_const": "cpp",
"span": "cpp",
"*.ipp": "cpp"
},
"rust.cfg_test": true,
"rust.clippy_preference": "on"
}

View file

@ -3,11 +3,14 @@ import("//third_party/v8/gni/v8.gni")
v8_static_library("rusty_v8") { v8_static_library("rusty_v8") {
sources = [ sources = [
"src/V8.cc",
"src/inspector/channel.cc", "src/inspector/channel.cc",
"src/inspector/client.cc", "src/inspector/client.cc",
"src/isolate.cc",
"src/locker.cc",
"src/platform/task.cc", "src/platform/task.cc",
"src/platform/mod.cc",
"src/string_buffer.cc", "src/string_buffer.cc",
"src/v8.cc",
] ]
deps = [ deps = [
":v8", ":v8",

7
Cargo.lock generated
View file

@ -43,6 +43,11 @@ dependencies = [
"backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.65" version = "0.2.65"
@ -58,6 +63,7 @@ name = "rusty_v8"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"cargo_gn 0.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_gn 0.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
"which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -78,6 +84,7 @@ dependencies = [
"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" "checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" "checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
"checksum which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "240a31163872f7e8e49f35b42b58485e35355b07eb009d9f3686733541339a69" "checksum which 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "240a31163872f7e8e49f35b42b58485e35355b07eb009d9f3686733541339a69"

View file

@ -5,6 +5,7 @@ authors = ["Bert Belder <bertbelder@gmail.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
lazy_static = "1.4.0"
libc = "0.2.65" libc = "0.2.65"
[build-dependencies] [build-dependencies]

View file

@ -45,6 +45,7 @@ fn main() {
if cfg!(target_os = "windows") { if cfg!(target_os = "windows") {
println!("cargo:rustc-link-lib=dylib=winmm"); println!("cargo:rustc-link-lib=dylib=winmm");
println!("cargo:rustc-link-lib=dylib=dbghelp");
} }
} }

View file

@ -1,13 +0,0 @@
#include "third_party/v8/include/v8.h"
extern "C" {
void v8__V8__SetFlagsFromCommandLine(int *argc, char **argv) {
v8::V8::SetFlagsFromCommandLine(argc, argv, true);
}
const char *v8__V8__GetVersion() { return v8::V8::GetVersion(); }
void v8__V8__Initialize() { v8::V8::Initialize(); }
bool v8__V8__Dispose() { return v8::V8::Dispose(); }
}

14
src/isolate.cc Normal file
View file

@ -0,0 +1,14 @@
#include "third_party/v8/include/v8.h"
using namespace v8;
extern "C" {
Isolate* v8__Isolate__New() {
Isolate::CreateParams params;
return Isolate::New(params);
}
void v8__Isolate__Dispose(Isolate& isolate) {
isolate.Dispose();
}
}

53
src/isolate.rs Normal file
View file

@ -0,0 +1,53 @@
use crate::support::Opaque;
use crate::v8::assert_initialized;
use std::ops::Deref;
extern "C" {
fn v8__Isolate__New() -> &'static mut UnlockedIsolate;
fn v8__Isolate__Dispose(this: &mut UnlockedIsolate) -> ();
}
#[repr(C)]
pub struct UnlockedIsolate(Opaque);
#[repr(C)]
pub struct LockedIsolate(Opaque);
#[repr(transparent)]
pub struct Isolate(&'static mut UnlockedIsolate);
impl Isolate {
pub fn new() -> Self {
// TODO: support CreateParams.
assert_initialized();
Self(unsafe { v8__Isolate__New() })
}
}
impl Drop for Isolate {
fn drop(&mut self) {
unsafe { v8__Isolate__Dispose(self.0) }
}
}
impl Deref for Isolate {
type Target = UnlockedIsolate;
fn deref(&self) -> &UnlockedIsolate {
self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::platform::*;
use crate::v8::*;
#[test]
fn test_isolate() {
initialize_platform(new_default_platform());
initialize();
//let isolate = Isolate::new();
dispose();
shutdown_platform();
}
}

View file

@ -1,16 +1,24 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
#![warn(clippy::all)] #![warn(clippy::all)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::new_without_default)]
#![allow(dead_code)] #![allow(dead_code)]
#[macro_use]
extern crate lazy_static;
extern crate libc; extern crate libc;
pub mod V8;
pub mod inspector; pub mod inspector;
pub mod isolate;
pub mod locker;
pub mod platform; pub mod platform;
pub mod string_buffer; pub mod string_buffer;
pub mod string_view; pub mod string_view;
pub mod support; pub mod support;
pub mod v8;
pub use isolate::Isolate;
pub use locker::Locker;
pub use string_buffer::StringBuffer; pub use string_buffer::StringBuffer;
pub use string_view::StringView; pub use string_view::StringView;

15
src/locker.cc Normal file
View file

@ -0,0 +1,15 @@
#include "support.h"
#include "third_party/v8/include/v8.h"
using namespace v8;
using namespace support;
extern "C" {
void v8__Locker__CONSTRUCT(uninit_t<Locker>& buf, Isolate* isolate) {
construct_in_place<Locker>(buf, isolate);
}
void v8__Locker__DESTRUCT(Locker& self) {
self.~Locker();
}
}

61
src/locker.rs Normal file
View file

@ -0,0 +1,61 @@
use std::marker::PhantomData;
use std::mem::MaybeUninit;
use std::ops::Deref;
use std::ops::DerefMut;
use crate::isolate::Isolate;
use crate::isolate::LockedIsolate;
use crate::isolate::UnlockedIsolate;
// class Locker {
// public:
// explicit Locker(Isolate* isolate);
// ~Locker();
// static bool IsLocked(Isolate* isolate);
// static bool IsActive();
// }
extern "C" {
fn v8__Locker__CONSTRUCT(
buf: &mut MaybeUninit<Locker>,
isolate: &UnlockedIsolate,
);
fn v8__Locker__DESTRUCT(this: &mut Locker);
}
#[repr(C)]
pub struct Locker<'a> {
has_lock: bool,
top_level: bool,
isolate: &'a mut LockedIsolate,
phantom: PhantomData<&'a Isolate>,
}
impl<'a> Locker<'a> {
fn new(isolate: &UnlockedIsolate) -> Self {
let mut buf = MaybeUninit::<Self>::uninit();
unsafe {
v8__Locker__CONSTRUCT(&mut buf, isolate);
buf.assume_init()
}
}
}
impl<'a> Drop for Locker<'a> {
fn drop(&mut self) {
unsafe { v8__Locker__DESTRUCT(self) }
}
}
impl<'a> Deref for Locker<'a> {
type Target = LockedIsolate;
fn deref(&self) -> &LockedIsolate {
self.isolate
}
}
impl<'a> DerefMut for Locker<'a> {
fn deref_mut(&mut self) -> &mut LockedIsolate {
self.isolate
}
}

20
src/platform/mod.cc Normal file
View file

@ -0,0 +1,20 @@
#include "../support.h"
#include "third_party/v8/include/libplatform/libplatform.h"
#include "third_party/v8/include/v8-platform.h"
#include <iostream>
using namespace v8;
using namespace v8::platform;
using namespace support;
extern "C" {
Platform* v8__platform__NewDefaultPlatform() {
// TODO: support optional arguments.
return NewDefaultPlatform().release();
}
void v8__Platform__DELETE(Platform& self) {
delete &self;
}
} // extern "C"

View file

@ -1,3 +1,28 @@
pub mod task; pub mod task;
pub use task::Task; pub use task::Task;
use crate::support::Delete;
use crate::support::Opaque;
use crate::support::UniquePtr;
extern "C" {
// TODO: move this to libplatform.rs?
fn v8__platform__NewDefaultPlatform() -> *mut Platform;
fn v8__Platform__DELETE(this: &'static mut Platform) -> ();
}
pub fn new_default_platform() -> UniquePtr<Platform> {
// TODO: support optional arguments.
unsafe { UniquePtr::from_raw(v8__platform__NewDefaultPlatform()) }
}
#[repr(C)]
pub struct Platform(Opaque);
impl Delete for Platform {
fn delete(&'static mut self) {
unsafe { v8__Platform__DELETE(self) }
}
}

View file

@ -1,7 +1,5 @@
#include "third_party/v8/include/v8-platform.h"
#include "../support.h" #include "../support.h"
#include "third_party/v8/include/v8-platform.h"
#include <iostream>
using namespace v8; using namespace v8;
using namespace support; using namespace support;

View file

@ -1,6 +1,7 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::size_of; use std::mem::size_of;
use std::mem::transmute; use std::mem::transmute;
use std::mem::MaybeUninit;
use std::ops::Deref; use std::ops::Deref;
use std::ops::DerefMut; use std::ops::DerefMut;
@ -37,6 +38,10 @@ where
pub unsafe fn from_raw(p: *mut T) -> Self { pub unsafe fn from_raw(p: *mut T) -> Self {
transmute(p) transmute(p)
} }
pub fn into_raw(self) -> *mut T {
unsafe { transmute(self) }
}
} }
impl<T> Deref for UniquePtr<T> impl<T> Deref for UniquePtr<T>
@ -111,3 +116,59 @@ impl<F> FieldOffset<F> {
.unwrap() .unwrap()
} }
} }
pub(crate) trait ConstructOnStack
where
Self: Sized,
{
type Args;
// The `buf` parameter represents a pointer to uninitialized memory.
fn construct(buf: &mut MaybeUninit<Self>, args: &Self::Args);
fn destruct(buf: &mut Self);
}
pub(crate) struct StackOnly<T>(MaybeUninit<T>)
where
T: ConstructOnStack;
impl<T> StackOnly<T>
where
T: ConstructOnStack,
{
unsafe fn uninit() -> Self {
Self(MaybeUninit::<T>::uninit())
}
unsafe fn init(&mut self, args: &T::Args) {
T::construct(&mut self.0, args);
}
}
impl<T> Deref for StackOnly<T>
where
T: ConstructOnStack,
{
type Target = T;
fn deref(&self) -> &T {
unsafe { &*(self as *const StackOnly<T> as *const T) }
}
}
impl<T> DerefMut for StackOnly<T>
where
T: ConstructOnStack,
{
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *(self as *mut StackOnly<T> as *mut T) }
}
}
impl<T> Drop for StackOnly<T>
where
T: ConstructOnStack,
{
fn drop(&mut self) {
T::destruct(&mut *self)
}
}

29
src/v8.cc Normal file
View file

@ -0,0 +1,29 @@
#include "third_party/v8/include/v8.h"
using namespace v8;
extern "C" {
void v8__V8__SetFlagsFromCommandLine(int* argc, char** argv) {
V8::SetFlagsFromCommandLine(argc, argv, true);
}
const char* v8__V8__GetVersion() {
return V8::GetVersion();
}
void v8__V8__InitializePlatform(Platform& platform) {
V8::InitializePlatform(&platform);
}
void v8__V8__Initialize() {
V8::Initialize();
}
bool v8__V8__Dispose() {
return V8::Dispose();
}
void v8__V8__ShutdownPlatform() {
V8::ShutdownPlatform();
}
}

View file

@ -4,22 +4,49 @@ use libc::c_char;
use libc::c_int; use libc::c_int;
use std::ffi::CStr; use std::ffi::CStr;
use std::ffi::CString; use std::ffi::CString;
use std::sync::Mutex;
use std::vec::Vec; use std::vec::Vec;
use crate::platform::Platform;
use crate::support::UniquePtr;
extern "C" { extern "C" {
pub fn v8__V8__SetFlagsFromCommandLine( pub fn v8__V8__SetFlagsFromCommandLine(
argc: *mut c_int, argc: *mut c_int,
argv: *mut *mut c_char, argv: *mut *mut c_char,
); );
pub fn v8__V8__GetVersion() -> *const c_char; pub fn v8__V8__GetVersion() -> *const c_char;
pub fn v8__V8__InitializePlatform(platform: &'static mut Platform);
pub fn v8__V8__Initialize(); pub fn v8__V8__Initialize();
pub fn v8__V8__Dispose() -> bool; pub fn v8__V8__Dispose() -> bool;
pub fn v8__V8__ShutdownPlatform() -> ();
}
#[derive(Debug, Eq, PartialEq)]
enum GlobalState {
Uninitialized,
PlatformInitialized,
Initialized,
Disposed,
PlatformShutdown,
}
use GlobalState::*;
lazy_static! {
static ref GLOBAL_STATE: Mutex<GlobalState> =
Mutex::new(GlobalState::Uninitialized);
}
pub fn assert_initialized() {
let global_state_guard = GLOBAL_STATE.lock().unwrap();
assert_eq!(*global_state_guard, Initialized);
} }
/// Pass the command line arguments to v8. /// Pass the command line arguments to v8.
/// The first element of args (which usually corresponds to the binary name) is /// The first element of args (which usually corresponds to the binary name) is
/// ignored. /// ignored.
/// Returns a vector of command line arguments that V8 did not understand. /// Returns a vector of command line arguments that V8 did not understand.
/// TODO: Check whether this is safe to do after globally initializing v8.
pub fn set_flags_from_command_line(args: Vec<String>) -> Vec<String> { pub fn set_flags_from_command_line(args: Vec<String>) -> Vec<String> {
// deno_set_v8_flags(int* argc, char** argv) mutates argc and argv to remove // deno_set_v8_flags(int* argc, char** argv) mutates argc and argv to remove
// flags that v8 understands. // flags that v8 understands.
@ -56,7 +83,6 @@ pub fn set_flags_from_command_line(args: Vec<String>) -> Vec<String> {
.collect() .collect()
} }
#[test]
fn test_set_flags_from_command_line() { fn test_set_flags_from_command_line() {
let r = set_flags_from_command_line(vec![ let r = set_flags_from_command_line(vec![
"binaryname".to_string(), "binaryname".to_string(),
@ -81,10 +107,23 @@ fn test_get_version() {
assert!(get_version().len() > 3); assert!(get_version().len() > 3);
} }
// TODO: V8::InitializePlatform does not actually take a UniquePtr but rather
// a raw pointer. This means that the Platform object is not released when
// V8::ShutdownPlatform is called.
pub fn initialize_platform(platform: UniquePtr<Platform>) {
let mut global_state_guard = GLOBAL_STATE.lock().unwrap();
assert_eq!(*global_state_guard, Uninitialized);
unsafe { v8__V8__InitializePlatform(&mut *platform.into_raw()) };
*global_state_guard = PlatformInitialized;
}
/// Initializes V8. This function needs to be called before the first Isolate /// Initializes V8. This function needs to be called before the first Isolate
/// is created. It always returns true. /// is created. It always returns true.
pub fn initialize() { pub fn initialize() {
unsafe { v8__V8__Initialize() } let mut global_state_guard = GLOBAL_STATE.lock().unwrap();
assert_eq!(*global_state_guard, PlatformInitialized);
unsafe { v8__V8__Initialize() };
*global_state_guard = Initialized;
} }
/// Releases any resources used by v8 and stops any utility threads /// Releases any resources used by v8 and stops any utility threads
@ -95,11 +134,16 @@ pub fn initialize() {
/// a process, this should happen automatically. It is only necessary /// a process, this should happen automatically. It is only necessary
/// to use if the process needs the resources taken up by v8. /// to use if the process needs the resources taken up by v8.
pub fn dispose() -> bool { pub fn dispose() -> bool {
unsafe { v8__V8__Dispose() } let mut global_state_guard = GLOBAL_STATE.lock().unwrap();
assert_eq!(*global_state_guard, Initialized);
assert_eq!(unsafe { v8__V8__Dispose() }, true);
*global_state_guard = Disposed;
true
} }
#[test] pub fn shutdown_platform() {
fn test_initialize_dispose() { let mut global_state_guard = GLOBAL_STATE.lock().unwrap();
initialize(); assert_eq!(*global_state_guard, Disposed);
dispose(); unsafe { v8__V8__ShutdownPlatform() };
*global_state_guard = PlatformShutdown;
} }