Skip to content
This repository was archived by the owner on Mar 29, 2024. It is now read-only.

Commit 950991f

Browse files
committed
Implement support to produce code cache after execute, closes #85
1 parent 636077c commit 950991f

File tree

5 files changed

+168
-17
lines changed

5 files changed

+168
-17
lines changed

src/php_v8_script_compiler.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,39 @@ static PHP_METHOD(ScriptCompiler, compileFunctionInContext)
268268
php_v8_get_or_create_value(return_value, local_function, php_v8_context->php_v8_isolate);
269269
}
270270

271+
static PHP_METHOD(ScriptCompiler, createCodeCache)
272+
{
273+
zval rv;
274+
275+
zval *php_v8_unbound_script_zv;
276+
zval *php_v8_source_string_zv;
277+
278+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "oo", &php_v8_unbound_script_zv, &php_v8_source_string_zv) == FAILURE) {
279+
return;
280+
}
281+
282+
php_v8_init();
283+
284+
PHP_V8_FETCH_UNBOUND_SCRIPT_WITH_CHECK(php_v8_unbound_script_zv, php_v8_unbound_script);
285+
PHP_V8_VALUE_FETCH_WITH_CHECK(php_v8_source_string_zv, php_v8_source_string);
286+
287+
PHP_V8_DATA_ISOLATES_CHECK(php_v8_unbound_script, php_v8_source_string);
288+
289+
PHP_V8_ENTER_STORED_ISOLATE(php_v8_unbound_script);
290+
291+
v8::Local<v8::UnboundScript> local_unbound_script = php_v8_unbound_script_get_local(php_v8_unbound_script);
292+
v8::Local<v8::String> local_source_string = php_v8_value_get_local_as<v8::String>(php_v8_source_string);
293+
294+
v8::ScriptCompiler::CachedData* cached_data = v8::ScriptCompiler::CreateCodeCache(local_unbound_script, local_source_string);
295+
296+
if (!cached_data) {
297+
PHP_V8_THROW_VALUE_EXCEPTION("Failed to create code cache");
298+
return;
299+
}
300+
301+
php_v8_create_cached_data(return_value, cached_data);
302+
}
303+
271304

272305
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_getCachedDataVersionTag, ZEND_RETURN_VALUE, 0, IS_DOUBLE, 0)
273306
ZEND_END_ARG_INFO()
@@ -291,12 +324,18 @@ PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_compileFunctionInContext,
291324
ZEND_ARG_TYPE_INFO(0, context_extensions, IS_ARRAY, 0)
292325
ZEND_END_ARG_INFO()
293326

327+
PHP_V8_ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_createCodeCache, ZEND_RETURN_VALUE, 2, V8\\ScriptCompiler\\CachedData, 0)
328+
ZEND_ARG_OBJ_INFO(0, unbound_script, V8\\UnboundScript, 0)
329+
ZEND_ARG_OBJ_INFO(0, source_string, V8\\StringValue, 0)
330+
ZEND_END_ARG_INFO()
331+
294332

295333
static const zend_function_entry php_v8_script_compiler_methods[] = {
296334
PHP_V8_ME(ScriptCompiler, getCachedDataVersionTag, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
297335
PHP_V8_ME(ScriptCompiler, compileUnboundScript, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
298336
PHP_V8_ME(ScriptCompiler, compile, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
299337
PHP_V8_ME(ScriptCompiler, compileFunctionInContext, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
338+
PHP_V8_ME(ScriptCompiler, createCodeCache, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
300339

301340
PHP_FE_END
302341
};

stubs/src/ScriptCompiler.php

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
namespace V8;
1717

1818

19+
use V8\ScriptCompiler\CachedData;
1920
use V8\ScriptCompiler\Source;
2021

2122

@@ -64,13 +65,8 @@ public static function getCachedDataVersionTag(): float
6465
* Cached data as part of the source object can be optionally produced to be
6566
* consumed later to speed up compilation of identical source scripts.
6667
*
67-
* Note that when producing cached data, the source must point to NULL for
68-
* cached data. When consuming cached data, the cached data must have been
69-
* produced by the same version of V8.
70-
*
71-
* \param source Script source code.
72-
* \return Compiled script object (context independent; for running it must be
73-
* bound to a context).
68+
* Note that when producing cached data, the source must have no cached data set.
69+
* When consuming cached data, the cached data must have been produced by the same version of V8.
7470
*
7571
* @param Context $context
7672
* @param Source $source
@@ -85,14 +81,6 @@ public static function compileUnboundScript(Context $context, Source $source, in
8581
/**
8682
* Compiles the specified script (bound to current context).
8783
*
88-
* \param source Script source code.
89-
* \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
90-
* using pre_data speeds compilation if it's done multiple times.
91-
* Owned by caller, no references are kept when this function returns.
92-
* \return Compiled script object, bound to the context that was active
93-
* when this function was called. When run it will always use this
94-
* context.
95-
*
9684
* @param Context $context
9785
* @param Source $source
9886
* @param int $options
@@ -110,8 +98,7 @@ public static function compile(Context $context, Source $source, int $options =
11098
* return function(args) { ... }
11199
* }
112100
*
113-
* It is possible to specify multiple context extensions (obj in the above
114-
* example).
101+
* It is possible to specify multiple context extensions (obj in the above example).
115102
*
116103
* @param Context $context
117104
* @param Source $source
@@ -123,4 +110,16 @@ public static function compile(Context $context, Source $source, int $options =
123110
public static function compileFunctionInContext(Context $context, Source $source, array $arguments = [], array $context_extensions = []): FunctionObject
124111
{
125112
}
113+
114+
/**
115+
* Creates and returns code cache for the specified unbound_script.
116+
*
117+
* @param UnboundScript $unbound_script
118+
* @param StringValue $source_string
119+
*
120+
* @return CachedData
121+
*/
122+
public static function createCodeCache(UnboundScript $unbound_script, StringValue $source_string): CachedData
123+
{
124+
}
126125
}

stubs/src/UnboundScript.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,22 @@
88
*/
99
class UnboundScript
1010
{
11+
/**
12+
* @var Isolate
13+
*/
14+
private $isolate;
15+
1116
private function __construct()
1217
{
1318
}
1419

20+
/**
21+
* @return Isolate
22+
*/
23+
public function getIsolate(): Isolate
24+
{
25+
}
26+
1527
/**
1628
* Binds the script to the currently entered context.
1729
*

tests/001-verify_extension_entities.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ class V8\ScriptCompiler
415415
public static function compileUnboundScript(V8\Context $context, V8\ScriptCompiler\Source $source, int $options): V8\UnboundScript
416416
public static function compile(V8\Context $context, V8\ScriptCompiler\Source $source, int $options): V8\Script
417417
public static function compileFunctionInContext(V8\Context $context, V8\ScriptCompiler\Source $source, array $arguments, array $context_extensions): V8\FunctionObject
418+
public static function createCodeCache(V8\UnboundScript $unbound_script, V8\StringValue $source_string): V8\ScriptCompiler\CachedData
418419

419420
class V8\ExceptionManager
420421
public static function createRangeError(V8\Context $context, V8\StringValue $message): V8\ObjectValue
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
--TEST--
2+
V8\ScriptCompiler::createCodeCache()
3+
--SKIPIF--
4+
<?php if (!extension_loaded("v8")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
8+
/** @var \Phpv8Testsuite $helper */
9+
$helper = require '.testsuite.php';
10+
11+
require '.v8-helpers.php';
12+
$v8_helper = new PhpV8Helpers($helper);
13+
14+
15+
$isolate = new V8\Isolate();
16+
$context = new V8\Context($isolate);
17+
18+
19+
$source_string = new V8\StringValue($isolate, "function f() { return 'abc'; }; f() + 'def'");
20+
$source = new \V8\ScriptCompiler\Source($source_string);
21+
$unbound = V8\ScriptCompiler::compileUnboundScript($context, $source);
22+
23+
$source_string_other = new V8\StringValue($isolate, "other; bad-'");
24+
25+
26+
$cache_data = V8\ScriptCompiler::createCodeCache($unbound, $source_string);
27+
28+
$helper->header('Testing with the source string is the same as used for original');
29+
30+
$helper->assert("Cache data created", null !== $cache_data);
31+
$helper->assert("Cache data is not empty", strlen($cache_data->getData()) > 1);
32+
$helper->assert("Cache data is not rejected", !$cache_data->isRejected());
33+
$helper->line();
34+
35+
{
36+
$helper->header('Test consuming code cache');
37+
38+
$source = new \V8\ScriptCompiler\Source($source_string, null, $cache_data);
39+
$helper->assert('Source cache data is set', $source->getCachedData() != null);
40+
$test_unbound = V8\ScriptCompiler::compileUnboundScript($context, $source, V8\ScriptCompiler::OPTION_CONSUME_CODE_CACHE);
41+
$helper->assert('Source cache data is still set', $source->getCachedData() != null);
42+
$helper->assert('Source cache data is not rejected', $source->getCachedData()->isRejected() === false);
43+
44+
$helper->pretty_dump('Script result', $test_unbound->bindToContext($context)->run($context)->toString($context)->value());
45+
}
46+
47+
48+
$helper->space();
49+
50+
$helper->header('Testing with the source string different from original');
51+
52+
$cache_data = V8\ScriptCompiler::createCodeCache($unbound, $source_string_other);
53+
54+
$helper->assert("Cache data created", null !== $cache_data);
55+
$helper->assert("Cache data is not empty", strlen($cache_data->getData()) > 1);
56+
$helper->assert("Cache data is not rejected", !$cache_data->isRejected());
57+
$helper->line();
58+
59+
{
60+
$helper->header('Test consuming code cache');
61+
62+
$source = new \V8\ScriptCompiler\Source($source_string, null, $cache_data);
63+
$helper->assert('Source cache data is set', $source->getCachedData() != null);
64+
$test_unbound = V8\ScriptCompiler::compileUnboundScript($context, $source, V8\ScriptCompiler::OPTION_CONSUME_CODE_CACHE);
65+
$helper->assert('Source cache data is still set', $source->getCachedData() != null);
66+
$helper->assert('Source cache data is not rejected', $source->getCachedData()->isRejected() === false);
67+
68+
$helper->pretty_dump('Script result', $test_unbound->bindToContext($context)->run($context)->toString($context)->value());
69+
}
70+
71+
72+
73+
?>
74+
--EXPECT--
75+
Testing with the source string is the same as used for original:
76+
----------------------------------------------------------------
77+
Cache data created: ok
78+
Cache data is not empty: ok
79+
Cache data is not rejected: ok
80+
81+
Test consuming code cache:
82+
--------------------------
83+
Source cache data is set: ok
84+
Source cache data is still set: ok
85+
Source cache data is not rejected: ok
86+
Script result: string(6) "abcdef"
87+
88+
89+
Testing with the source string different from original:
90+
-------------------------------------------------------
91+
Cache data created: ok
92+
Cache data is not empty: ok
93+
Cache data is not rejected: ok
94+
95+
Test consuming code cache:
96+
--------------------------
97+
Source cache data is set: ok
98+
Source cache data is still set: ok
99+
Source cache data is not rejected: ok
100+
Script result: string(6) "abcdef"

0 commit comments

Comments
 (0)