Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,14 @@ class V8Js
/* Methods */

/**
* Initializes and starts V8 engine and Returns new V8Js object with it's own V8 context.
* Initializes and starts V8 engine and returns new V8Js object with it's own V8 context.
* @param string $object_name
* @param array $variables
* @param array $extensions
* @param bool $report_uncaught_exceptions
* @param string $snapshot_blob
*/
public function __construct($object_name = "PHP", array $variables = NULL, array $extensions = NULL, $report_uncaught_exceptions = TRUE)
public function __construct($object_name = "PHP", array $variables = [], array $extensions = [], $report_uncaught_exceptions = TRUE, $snapshot_blob = NULL)
{}

/**
Expand Down Expand Up @@ -174,6 +175,14 @@ class V8Js
*/
public static function getExtensions()
{}

/**
* Creates a custom V8 heap snapshot with the provided JavaScript source embedded.
* @param string $embed_source
* @return string|false
*/
public static function createSnapshot($embed_source)
{}
}

final class V8JsScriptException extends Exception
Expand Down
98 changes: 92 additions & 6 deletions config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,6 @@ int main ()
AC_MSG_ERROR([could not determine libv8 version])
fi

AC_LANG_RESTORE
LIBS=$old_LIBS
LDFLAGS=$old_LDFLAGS
CPPFLAGS=$old_CPPFLAGS

if test "$V8_API_VERSION" -ge 3029036 ; then
dnl building for v8 3.29.36 or later, which requires us to
dnl initialize and provide a platform; hence we need to
Expand Down Expand Up @@ -169,10 +164,101 @@ int main ()
AC_MSG_ERROR([Please provide $static_link_extra_file next to the libv8.so, see README.md for details])
fi

LDFLAGS="$LDFLAGS $static_link_dir/$static_link_extra_file"
LDFLAGS_libplatform="$static_link_dir/$static_link_extra_file"
done

# modify flags for (possibly) succeeding V8 startup check
CPPFLAGS="$CPPFLAGS -I$V8_DIR"
LIBS="$LIBS $LDFLAGS_libplatform"
fi

if test "$V8_API_VERSION" -ge 4004010 ; then
dnl building for v8 4.4.10 or later, which requires us to
dnl provide startup data, if V8 wasn't compiled with snapshot=off.
AC_MSG_CHECKING([whether V8 requires startup data])
AC_TRY_RUN([
#include <v8.h>
#include <libplatform/libplatform.h>
#include <stdlib.h>
#include <string.h>

#if PHP_V8_API_VERSION >= 4004010
class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
public:
virtual void* Allocate(size_t length) {
void* data = AllocateUninitialized(length);
return data == NULL ? data : memset(data, 0, length);
}
virtual void* AllocateUninitialized(size_t length) { return malloc(length); }
virtual void Free(void* data, size_t) { free(data); }
};
#endif

int main ()
{
v8::Platform *v8_platform = v8::platform::CreateDefaultPlatform();
v8::V8::InitializePlatform(v8_platform);
v8::V8::Initialize();

#if PHP_V8_API_VERSION >= 4004044
static ArrayBufferAllocator array_buffer_allocator;
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = &array_buffer_allocator;

v8::Isolate::New(create_params);
#else /* PHP_V8_API_VERSION < 4004044 */
v8::Isolate::New();
#endif
return 0;
}
], [
AC_MSG_RESULT([no])
], [
AC_MSG_RESULT([yes])
AC_DEFINE([PHP_V8_USE_EXTERNAL_STARTUP_DATA], [1], [Whether V8 requires (and can be provided with custom versions of) external startup data])

SEARCH_PATH="$V8_DIR/lib"

AC_MSG_CHECKING([for natives_blob.bin])
SEARCH_FOR="natives_blob.bin"

for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
AC_MSG_RESULT([found ($i/$SEARCH_FOR)])
AC_DEFINE_UNQUOTED([PHP_V8_NATIVES_BLOB_PATH], "$i/$SEARCH_FOR", [Full path to natives_blob.bin file])
native_blob_found=1
fi
done

if test -z "$native_blob_found"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Please provide V8 native blob as needed])
fi

AC_MSG_CHECKING([for snapshot_blob.bin])
SEARCH_FOR="snapshot_blob.bin"

for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
AC_MSG_RESULT([found ($i/$SEARCH_FOR)])
AC_DEFINE_UNQUOTED([PHP_V8_SNAPSHOT_BLOB_PATH], "$i/$SEARCH_FOR", [Full path to snapshot_blob.bin file])
snapshot_blob_found=1
fi
done

if test -z "$snapshot_blob_found"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Please provide V8 snapshot blob as needed])
fi
])
fi

AC_LANG_RESTORE
LIBS=$old_LIBS
LDFLAGS="$old_LDFLAGS $LDFLAGS_libplatform"
CPPFLAGS=$old_CPPFLAGS


PHP_NEW_EXTENSION(v8js, [ \
v8js_array_access.cc \
v8js.cc \
Expand Down
85 changes: 73 additions & 12 deletions v8js_class.cc
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ static void v8js_free_storage(void *object TSRMLS_DC) /* {{{ */
c->modules_stack.~vector();
c->modules_base.~vector();

#if defined(PHP_V8_USE_EXTERNAL_STARTUP_DATA) && PHP_V8_API_VERSION >= 4004044
if (c->snapshot_blob.data) {
efree((void*)c->snapshot_blob.data);
}
#endif

efree(object);
}
/* }}} */
Expand Down Expand Up @@ -327,12 +333,12 @@ static void v8js_fatal_error_handler(const char *location, const char *message)
((key_len == sizeof(mname)) && \
!strncasecmp(key, mname, key_len - 1))

/* {{{ proto void V8Js::__construct([string object_name [, array variables [, array extensions [, bool report_uncaught_exceptions]]])
/* {{{ proto void V8Js::__construct([string object_name [, array variables [, array extensions [, bool report_uncaught_exceptions [, string snapshot_blob]]]]])
__construct for V8Js */
static PHP_METHOD(V8Js, __construct)
{
char *object_name = NULL, *class_name = NULL;
int object_name_len = 0, free = 0;
char *object_name = NULL, *class_name = NULL, *snapshot_blob = NULL;
int object_name_len = 0, free = 0, snapshot_blob_len = 0;
zend_uint class_name_len = 0;
zend_bool report_uncaught = 1;
zval *vars_arr = NULL, *exts_arr = NULL;
Expand All @@ -346,7 +352,7 @@ static PHP_METHOD(V8Js, __construct)
return;
}

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|saab", &object_name, &object_name_len, &vars_arr, &exts_arr, &report_uncaught) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|saabs", &object_name, &object_name_len, &vars_arr, &exts_arr, &report_uncaught, &snapshot_blob, &snapshot_blob_len) == FAILURE) {
return;
}

Expand All @@ -360,10 +366,20 @@ static PHP_METHOD(V8Js, __construct)

#if PHP_V8_API_VERSION >= 4004044
static ArrayBufferAllocator array_buffer_allocator;
static v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = &array_buffer_allocator;
c->isolate = v8::Isolate::New(create_params);
#else
new (&c->create_params) v8::Isolate::CreateParams();
c->create_params.array_buffer_allocator = &array_buffer_allocator;

#ifdef PHP_V8_USE_EXTERNAL_STARTUP_DATA
new (&c->snapshot_blob) v8::StartupData();
if (snapshot_blob && snapshot_blob_len) {
c->snapshot_blob.data = snapshot_blob;
c->snapshot_blob.raw_size = snapshot_blob_len;
c->create_params.snapshot_blob = &c->snapshot_blob;
}
#endif /* PHP_V8_USE_EXTERNAL_STARTUP_DATA */

c->isolate = v8::Isolate::New(c->create_params);
#else /* PHP_V8_API_VERSION < 4004044 */
c->isolate = v8::Isolate::New();
#endif

Expand Down Expand Up @@ -991,6 +1007,10 @@ static int v8js_register_extension(char *name, uint name_len, char *source, uint
}
/* }}} */



/* ## Static methods ## */

/* {{{ proto bool V8Js::registerExtension(string ext_name, string script [, array deps [, bool auto_enable]])
*/
static PHP_METHOD(V8Js, registerExtension)
Expand All @@ -1015,8 +1035,6 @@ static PHP_METHOD(V8Js, registerExtension)
}
/* }}} */

/* ## Static methods ## */

/* {{{ proto array V8Js::getExtensions()
*/
static PHP_METHOD(V8Js, getExtensions)
Expand Down Expand Up @@ -1063,6 +1081,40 @@ static PHP_METHOD(V8Js, getExtensions)
}
/* }}} */

#ifdef PHP_V8_USE_EXTERNAL_STARTUP_DATA
/* {{{ proto string|bool V8Js::createSnapshot(string embed_source)
*/
static PHP_METHOD(V8Js, createSnapshot)
{
char *script;
int script_len;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &script, &script_len) == FAILURE) {
return;
}

if (!script_len) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Script cannot be empty");
RETURN_FALSE;
}

/* Initialize V8, if not already done. */
v8js_v8_init(TSRMLS_C);

v8::StartupData snapshot_blob = v8::V8::CreateSnapshotDataBlob(script);

if (!snapshot_blob.data) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to create V8 heap snapshot. Check $embed_source for errors.");
RETURN_FALSE;
}

RETVAL_STRINGL(snapshot_blob.data, snapshot_blob.raw_size, 1);
delete[] snapshot_blob.data;
}
/* }}} */
#endif /* PHP_V8_USE_EXTERNAL_STARTUP_DATA */


/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_construct, 0, 0, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L1119 - L1124: I notice there is no argument defined for the new snapshot blob which is defined as a parameter above?

ZEND_ARG_INFO(0, object_name)
Expand Down Expand Up @@ -1126,6 +1178,12 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_v8js_getextensions, 0)
ZEND_END_ARG_INFO()

#ifdef PHP_V8_USE_EXTERNAL_STARTUP_DATA
ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_createsnapshot, 0, 0, 1)
ZEND_ARG_INFO(0, script)
ZEND_END_ARG_INFO()
#endif

ZEND_BEGIN_ARG_INFO_EX(arginfo_v8js_settimelimit, 0, 0, 1)
ZEND_ARG_INFO(0, time_limit)
ZEND_END_ARG_INFO()
Expand All @@ -1147,10 +1205,13 @@ const zend_function_entry v8js_methods[] = { /* {{{ */
PHP_ME(V8Js, clearPendingException, arginfo_v8js_clearpendingexception, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, setModuleNormaliser, arginfo_v8js_setmodulenormaliser, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, setModuleLoader, arginfo_v8js_setmoduleloader, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, registerExtension, arginfo_v8js_registerextension, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(V8Js, getExtensions, arginfo_v8js_getextensions, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(V8Js, setTimeLimit, arginfo_v8js_settimelimit, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, setMemoryLimit, arginfo_v8js_setmemorylimit, ZEND_ACC_PUBLIC)
PHP_ME(V8Js, registerExtension, arginfo_v8js_registerextension, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
PHP_ME(V8Js, getExtensions, arginfo_v8js_getextensions, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
#ifdef PHP_V8_USE_EXTERNAL_STARTUP_DATA
PHP_ME(V8Js, createSnapshot, arginfo_v8js_createsnapshot, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
#endif
{NULL, NULL, NULL}
};
/* }}} */
Expand Down
11 changes: 10 additions & 1 deletion v8js_class.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2013 The PHP Group |
| Copyright (c) 1997-2016 The PHP Group |
+----------------------------------------------------------------------+
| http://www.opensource.org/licenses/mit-license.php MIT License |
+----------------------------------------------------------------------+
| Author: Jani Taskinen <[email protected]> |
| Author: Patrick Reilly <[email protected]> |
| Author: Stefan Siegl <[email protected]> |
+----------------------------------------------------------------------+
*/

Expand Down Expand Up @@ -67,6 +68,14 @@ struct v8js_ctx {
std::vector<v8js_accessor_ctx *> accessor_list;
std::vector<struct _v8js_script *> script_objects;
char *tz;

#if PHP_V8_API_VERSION >= 4004044
v8::Isolate::CreateParams create_params;
#ifdef PHP_V8_USE_EXTERNAL_STARTUP_DATA
v8::StartupData snapshot_blob;
#endif
#endif

#ifdef ZTS
void ***zts_ctx;
#endif
Expand Down
Loading