Skip to content

Commit 46c8e21

Browse files
trevnorrisMyles Borins
authored and
Myles Borins
committed
deps: backport 1f8555 from v8's upstream
Original commit message: api: introduce SealHandleScope When debugging Handle leaks in io.js we found it very convenient to be able to Seal some specific (root in our case) scope to prevent Handle allocations in it, and easily find leakage. R=yangguo BUG= Review URL: https://codereview.chromium.org/1079713002 Cr-Commit-Position: refs/heads/master@{#27766} Should help us identify and fix Handle leaks in core and user-space code. PR-URL: #3945 Reviewed-By: Fedor Indutny <fedor@indutny.com> Reviewed-By: James Snell <jasnell@gmail.com>
1 parent a8bb5c7 commit 46c8e21

File tree

5 files changed

+76
-4
lines changed

5 files changed

+76
-4
lines changed

deps/v8/include/v8.h

+21
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,27 @@ class ScriptOrigin {
944944
};
945945

946946

947+
class V8_EXPORT SealHandleScope {
948+
public:
949+
SealHandleScope(Isolate* isolate);
950+
~SealHandleScope();
951+
952+
private:
953+
// Make it hard to create heap-allocated or illegal handle scopes by
954+
// disallowing certain operations.
955+
SealHandleScope(const SealHandleScope&);
956+
void operator=(const SealHandleScope&);
957+
void* operator new(size_t size);
958+
void operator delete(void*, size_t);
959+
960+
internal::Isolate* isolate_;
961+
int prev_level_;
962+
internal::Object** prev_limit_;
963+
};
964+
965+
966+
967+
947968
/**
948969
* A compiled JavaScript script, not yet tied to a Context.
949970
*/

deps/v8/src/api.cc

+21
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,27 @@ i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
637637
}
638638

639639

640+
SealHandleScope::SealHandleScope(Isolate* isolate) {
641+
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
642+
643+
isolate_ = internal_isolate;
644+
i::HandleScopeData* current = internal_isolate->handle_scope_data();
645+
prev_limit_ = current->limit;
646+
current->limit = current->next;
647+
prev_level_ = current->level;
648+
current->level = 0;
649+
}
650+
651+
652+
SealHandleScope::~SealHandleScope() {
653+
i::HandleScopeData* current = isolate_->handle_scope_data();
654+
DCHECK_EQ(0, current->level);
655+
current->level = prev_level_;
656+
DCHECK_EQ(current->next, current->limit);
657+
current->limit = prev_limit_;
658+
}
659+
660+
640661
void Context::Enter() {
641662
i::Handle<i::Context> env = Utils::OpenHandle(this);
642663
i::Isolate* isolate = env->GetIsolate();

deps/v8/src/api.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -642,17 +642,14 @@ void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
642642
while (!blocks_.is_empty()) {
643643
internal::Object** block_start = blocks_.last();
644644
internal::Object** block_limit = block_start + kHandleBlockSize;
645-
#ifdef DEBUG
645+
646646
// SealHandleScope may make the prev_limit to point inside the block.
647647
if (block_start <= prev_limit && prev_limit <= block_limit) {
648648
#ifdef ENABLE_HANDLE_ZAPPING
649649
internal::HandleScope::ZapRange(prev_limit, block_limit);
650650
#endif
651651
break;
652652
}
653-
#else
654-
if (prev_limit == block_limit) break;
655-
#endif
656653

657654
blocks_.RemoveLast();
658655
#ifdef ENABLE_HANDLE_ZAPPING

deps/v8/test/cctest/cctest.status

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
# they don't fail then test.py has failed.
4444
'test-serialize/TestThatAlwaysFails': [FAIL],
4545
'test-serialize/DependentTestThatAlwaysFails': [FAIL],
46+
'test-api/SealHandleScope': [FAIL],
4647

4748
# This test always fails. It tests that LiveEdit causes abort when turned off.
4849
'test-debug/LiveEditDisabled': [FAIL],

deps/v8/test/cctest/test-api.cc

+32
Original file line numberDiff line numberDiff line change
@@ -20625,6 +20625,38 @@ void CallCompletedCallbackException() {
2062520625
}
2062620626

2062720627

20628+
TEST(SealHandleScope) {
20629+
v8::Isolate* isolate = CcTest::isolate();
20630+
v8::HandleScope handle_scope(isolate);
20631+
LocalContext env;
20632+
20633+
v8::SealHandleScope seal(isolate);
20634+
20635+
// Should fail
20636+
v8::Local<v8::Object> obj = v8::Object::New(isolate);
20637+
20638+
USE(obj);
20639+
}
20640+
20641+
20642+
TEST(SealHandleScopeNested) {
20643+
v8::Isolate* isolate = CcTest::isolate();
20644+
v8::HandleScope handle_scope(isolate);
20645+
LocalContext env;
20646+
20647+
v8::SealHandleScope seal(isolate);
20648+
20649+
{
20650+
v8::HandleScope handle_scope(isolate);
20651+
20652+
// Should work
20653+
v8::Local<v8::Object> obj = v8::Object::New(isolate);
20654+
20655+
USE(obj);
20656+
}
20657+
}
20658+
20659+
2062820660
TEST(CallCompletedCallbackOneException) {
2062920661
LocalContext env;
2063020662
v8::HandleScope scope(env->GetIsolate());

0 commit comments

Comments
 (0)