Skip to content

Commit

Permalink
Add Isolate creation and disposal for Yao (dev)
Browse files Browse the repository at this point in the history
  • Loading branch information
trheyi committed Dec 25, 2023
1 parent a6a98f8 commit c0d27a6
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 43 deletions.
18 changes: 0 additions & 18 deletions isolate.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,6 @@ func NewIsolate() *Isolate {
return iso
}

// NewIsolateHeapSize creates a new V8 isolate. Only one thread may access
// a given isolate at a time, but different threads may access
// different isolates simultaneously.
// When an isolate is no longer used its resources should be freed
// by calling iso.Dispose().
// An *Isolate can be used as a v8go.ContextOption to create a new
// Context, rather than creating a new default Isolate.
func NewIsolateHeapSize(maximumHeapSizeInMb int) *Isolate {
initializeIfNecessary()
iso := &Isolate{
ptr: C.NewIsolateHeapSize(C.int(maximumHeapSizeInMb)),
cbs: make(map[int]FunctionCallback),
}
iso.null = newValueNull(iso)
iso.undefined = newValueUndefined(iso)
return iso
}

// TerminateExecution terminates forcefully the current thread
// of JavaScript execution in the given isolate.
func (i *Isolate) TerminateExecution() {
Expand Down
84 changes: 60 additions & 24 deletions v8go.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,66 @@ m_unboundScript* tracked_unbound_script(m_ctx* ctx, m_unboundScript* us) {

extern "C" {

/********** Yao App Enine **********/
static IsolatePtr globalIsolate = nullptr;

void YaoDispose() {
if (globalIsolate != nullptr ) {
globalIsolate->Dispose();
globalIsolate = nullptr;
}
}

extern IsolatePtr YaoNewIsolate() {
Isolate::CreateParams params;
params.array_buffer_allocator = default_allocator;

Isolate* iso = Isolate::New(params);
Locker locker(iso);
Isolate::Scope isolate_scope(iso);
HandleScope handle_scope(iso);

iso->SetCaptureStackTraceForUncaughtExceptions(true);

// Create a Context for internal use
m_ctx* ctx = new m_ctx;
ctx->ptr.Reset(iso, Context::New(iso));
ctx->iso = iso;
iso->SetData(0, ctx);
return iso;
}


extern IsolatePtr YaoNewIsolateFromGlobal() {
if (globalIsolate == nullptr) {
return nullptr;
}

IsolatePtr ptr = YaoCopyIsolate(globalIsolate);
return ptr;
}


extern IsolatePtr YaoCopyIsolate( IsolatePtr iso ) {
Isolate::CreateParams params;
params.array_buffer_allocator = default_allocator;
return iso->New(params);
}


// Should call in the main thread only
extern void YaoIsolateAsGlobal( IsolatePtr iso ) {
if (globalIsolate != nullptr) {
globalIsolate->Dispose();
globalIsolate = nullptr;
}
globalIsolate = YaoCopyIsolate(iso);
}

/**** ----- END ------- ****/



/********** Isolate **********/

#define ISOLATE_SCOPE(iso) \
Expand Down Expand Up @@ -167,30 +227,6 @@ IsolatePtr NewIsolate() {
return iso;
}

extern IsolatePtr NewIsolateHeapSize(int maximum_heap_size_in_mb) {
Isolate::CreateParams params;
params.array_buffer_allocator = default_allocator;

// v8::ResourceConstraints constraints;
// // constraints.ConfigureDefaultsFromHeapSize(0, 1ULL * maximum_heap_size_in_mb * 1024 * 1024);
// constraints.set_max_old_generation_size_in_bytes(1ULL * maximum_heap_size_in_mb * 1024 * 1024);
// params.constraints = constraints;

Isolate* iso = Isolate::New(params);
Locker locker(iso);
Isolate::Scope isolate_scope(iso);
HandleScope handle_scope(iso);

iso->SetCaptureStackTraceForUncaughtExceptions(true);

// Create a Context for internal use
m_ctx* ctx = new m_ctx;
ctx->ptr.Reset(iso, Context::New(iso));
ctx->iso = iso;
iso->SetData(0, ctx);
return iso;
}

static inline m_ctx* isolateInternalContext(Isolate* iso) {
return static_cast<m_ctx*>(iso->GetData(0));
}
Expand Down
12 changes: 11 additions & 1 deletion v8go.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,19 @@ typedef struct {
int sign_bit;
} ValueBigInt;


/**** Yao App Engine ****/

extern void YaoDispose();
extern IsolatePtr YaoNewIsolate();
extern IsolatePtr YaoCopyIsolate( IsolatePtr iso );
extern IsolatePtr YaoNewIsolateFromGlobal();
extern void YaoIsolateAsGlobal( IsolatePtr iso );

/**** ----- END ------- ****/

extern void Init();
extern IsolatePtr NewIsolate();
extern IsolatePtr NewIsolateHeapSize(int maximum_heap_size_in_mb);
extern void IsolatePerformMicrotaskCheckpoint(IsolatePtr ptr);
extern void IsolateDispose(IsolatePtr ptr);
extern void IsolateTerminateExecution(IsolatePtr ptr);
Expand Down
78 changes: 78 additions & 0 deletions yao.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package v8go

import (
"fmt"
"unsafe"
)

// #include "v8go.h"
// #include <stdlib.h>
import "C"

// YaoNewIsolate creates a new V8 isolate. Only one thread may access
// a given isolate at a time, but different threads may access
// different isolates simultaneously.
// When an isolate is no longer used its resources should be freed
// by calling iso.Dispose().
// An *Isolate can be used as a v8go.ContextOption to create a new
// Context, rather than creating a new default Isolate.
func YaoNewIsolate() *Isolate {
iso := &Isolate{
ptr: C.YaoNewIsolate(),
cbs: make(map[int]FunctionCallback),
}
iso.null = newValueNull(iso)
iso.undefined = newValueUndefined(iso)
return iso
}

// YaoNewIsolateFromGlobal creates a new V8 isolate from global.
func YaoNewIsolateFromGlobal() (*Isolate, error) {

ptr := C.YaoNewIsolateFromGlobal()
if ptr == nil {
return nil, fmt.Errorf("YaoNewIsolateFromGlobal failed")
}

iso := &Isolate{
ptr: ptr,
cbs: make(map[int]FunctionCallback),
}

return iso, nil
}

// YaoDispose will dispose the Isolate VM; subsequent calls will panic.
func YaoDispose() {
C.YaoDispose()
}

// Copy copies the current isolate.
func (iso *Isolate) Copy() (*Isolate, error) {
if iso == nil || iso.ptr == nil {
return nil, fmt.Errorf("invalid isolate")
}
new := &Isolate{
ptr: C.YaoCopyIsolate(iso.ptr),
cbs: make(map[int]FunctionCallback),
}
return new, nil
}

// AsGlobal makes the isolate into a global object.
func (iso *Isolate) AsGlobal() {
C.YaoIsolateAsGlobal(iso.ptr)
}

// YaoInit initializes V8 with the given heap size limit.
func YaoInit(heapSizeLimitMB uint) {
v8once.Do(func() {
cflags := C.CString("--no-freeze_flags_after_init")
if heapSizeLimitMB > 0 {
cflags = C.CString(fmt.Sprintf("--no-freeze_flags_after_init --max_old_space_size=%d", heapSizeLimitMB))
}
defer C.free(unsafe.Pointer(cflags))
C.SetFlags(cflags)
C.Init()
})
}
73 changes: 73 additions & 0 deletions yao_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package v8go_test

import (
"fmt"
"testing"

v8 "rogchap.com/v8go"
)

func TestYaoVersionPrint(t *testing.T) {
v := v8.Version()
fmt.Println("Version", v)
}

func TestYaoInit(t *testing.T) {
t.Parallel()
v8.YaoInit(1024)
defer v8.YaoDispose()

iso := v8.YaoNewIsolate()
defer iso.Dispose()

// stat := iso.GetHeapStatistics()
// if stat.HeapSizeLimit > 1100*1024*1024 {
// t.Errorf("HeapSizeLimit error %d", stat.HeapSizeLimit)
// }
}

func TestYaoCopyIsolate(t *testing.T) {
t.Parallel()
v8.YaoInit(1024)
defer v8.YaoDispose()

iso := v8.YaoNewIsolate()
defer iso.Dispose()

new, err := iso.Copy()
if err != nil {
t.Error(err)
}
defer new.Dispose()
}

func TestYaoIsolateAsGlobal(t *testing.T) {

v8.YaoInit(1024)
defer v8.YaoDispose()

iso := v8.YaoNewIsolate()
defer iso.Dispose()

iso.AsGlobal()
}

func TestYaoNewIsolateFromGlobal(t *testing.T) {
v8.YaoInit(1024)
defer v8.YaoDispose()

iso := v8.YaoNewIsolate()
iso.AsGlobal()
iso.Dispose()
iso = nil

new, err := v8.YaoNewIsolateFromGlobal()
if err != nil {
t.Error(err)
}

if new == nil {
t.Errorf("new is nil")
}
defer new.Dispose()
}

0 comments on commit c0d27a6

Please sign in to comment.