0
0
mirror of https://github.com/phpv8/v8js.git synced 2024-11-09 15:18:41 +00:00

Use isolate->RequestInterrupt to get heap size

This commit is contained in:
Stefan Siegl 2014-12-08 22:19:29 +00:00
parent 0004626015
commit 2252169a98
2 changed files with 59 additions and 25 deletions

View File

@ -7,9 +7,9 @@ Test V8::setTimeLimit() : Time limit can be prolonged
$JS = <<< EOT
var text = "abcdefghijklmnopqrstuvwyxz0123456789";
/* Spend 20 * >10ms in the loop, i.e. at least 200ms; hence
/* Spend 30 * >10ms in the loop, i.e. at least 300ms; hence
* it should be killed if prolonging doesn't work. */
for (var j = 0; j < 20; ++j) {
for (var j = 0; j < 30; ++j) {
PHP.prolongTimeLimit();
var start = (new Date()).getTime();
var encoded = encodeURI(text);
@ -22,10 +22,10 @@ for (var j = 0; j < 20; ++j) {
EOT;
$v8 = new V8Js();
$v8->setTimeLimit(25);
$v8->setTimeLimit(100);
$v8->prolongTimeLimit = function() use ($v8) {
$v8->setTimeLimit(25);
$v8->setTimeLimit(100);
};
$v8->executeString($JS);

76
v8js.cc
View File

@ -1081,40 +1081,74 @@ static void php_v8js_terminate_execution(php_v8js_ctx *c TSRMLS_DC)
// This timer will be removed from stack by the parent thread.
}
static void php_v8js_timer_interrupt_handler(v8::Isolate *isolate, void *data) { /* {{{ */
#ifdef ZTS
TSRMLS_D = (void ***) data;
#endif
if (!V8JSG(timer_stack).size()) {
return;
}
v8::Locker locker(isolate);
v8::HeapStatistics hs;
isolate->GetHeapStatistics(&hs);
V8JSG(timer_mutex).lock();
for (std::deque< php_v8js_timer_ctx* >::iterator it = V8JSG(timer_stack).begin();
it != V8JSG(timer_stack).end(); it ++) {
php_v8js_timer_ctx *timer_ctx = *it;
php_v8js_ctx *c = timer_ctx->v8js_ctx;
if(c->isolate != isolate || timer_ctx->killed) {
continue;
}
if (timer_ctx->memory_limit > 0 && hs.used_heap_size() > timer_ctx->memory_limit) {
timer_ctx->killed = true;
php_v8js_terminate_execution(c TSRMLS_CC);
c->memory_limit_hit = true;
}
}
V8JSG(timer_mutex).unlock();
}
/* }}} */
static void php_v8js_timer_thread(TSRMLS_D)
{
while (!V8JSG(timer_stop)) {
std::chrono::time_point<std::chrono::high_resolution_clock> now = std::chrono::high_resolution_clock::now();
v8::HeapStatistics hs;
V8JSG(timer_mutex).lock();
if (V8JSG(timer_stack).size()) {
// Get the current timer context
php_v8js_timer_ctx *timer_ctx = V8JSG(timer_stack).front();
php_v8js_ctx *c = timer_ctx->v8js_ctx;
std::chrono::time_point<std::chrono::high_resolution_clock> now = std::chrono::high_resolution_clock::now();
// Get memory usage statistics for the isolate
c->isolate->GetHeapStatistics(&hs);
if (timer_ctx->time_limit > 0 && now > timer_ctx->time_point &&
!timer_ctx->killed) {
timer_ctx->killed = true;
php_v8js_terminate_execution(c TSRMLS_CC);
V8JSG(timer_mutex).lock();
c->time_limit_hit = true;
V8JSG(timer_mutex).unlock();
if(timer_ctx->killed) {
/* execution already terminated, nothing to check anymore,
* but wait for caller to pop this timer context. */
}
if (timer_ctx->memory_limit > 0 && hs.used_heap_size() > timer_ctx->memory_limit &&
!timer_ctx->killed) {
else if(timer_ctx->time_limit > 0 && now > timer_ctx->time_point) {
timer_ctx->killed = true;
php_v8js_terminate_execution(c TSRMLS_CC);
V8JSG(timer_mutex).lock();
c->memory_limit_hit = true;
V8JSG(timer_mutex).unlock();
c->time_limit_hit = true;
}
else if (timer_ctx->memory_limit > 0) {
/* If a memory_limit is set, we need to interrupt execution
* and check heap size within the callback. We must *not*
* directly call GetHeapStatistics here, since we don't have
* a v8::Locker on the isolate, but are expected to hold one,
* and cannot aquire it as v8 is executing the script ... */
void *data = NULL;
#ifdef ZTS
data = (void *) TSRMLS_C;
#endif
c->isolate->RequestInterrupt(php_v8js_timer_interrupt_handler, data);
}
}
V8JSG(timer_mutex).unlock();
// Sleep for 10ms
#ifdef _WIN32