Reviewers: yangguo, indutny,
Message:
Thank you!
Description:
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=
Please review this at https://codereview.chromium.org/1079713002/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+73, -4 lines):
M include/v8.h
M src/api.h
M src/api.cc
M test/cctest/cctest.status
M test/cctest/test-api.cc
Index: include/v8.h
diff --git a/include/v8.h b/include/v8.h
index
8019a4522b4bafb811263bc39bb53e516fbeb2b6..d94e9b32b854826ba221abb3948f057fb74a9a26
100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1018,6 +1018,24 @@ class V8_EXPORT EscapableHandleScope : public
HandleScope {
internal::Object** escape_slot_;
};
+class V8_EXPORT SealHandleScope {
+ public:
+ SealHandleScope(Isolate* isolate);
+ ~SealHandleScope();
+
+ private:
+ // Make it hard to create heap-allocated or illegal handle scopes by
+ // disallowing certain operations.
+ SealHandleScope(const SealHandleScope&);
+ void operator=(const SealHandleScope&);
+ void* operator new(size_t size);
+ void operator delete(void*, size_t);
+
+ internal::Isolate* isolate_;
+ int prev_level_;
+ internal::Object** prev_limit_;
+};
+
// --- Special objects ---
Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index
28c84106df4c260cfbd2e96972a12efcd1f10964..733214ec076712b31538853fe24fcc03162f80b9
100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -674,6 +674,27 @@ i::Object** EscapableHandleScope::Escape(i::Object**
escape_value) {
}
+SealHandleScope::SealHandleScope(Isolate* isolate) {
+ i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
+
+ isolate_ = internal_isolate;
+ i::HandleScopeData* current = internal_isolate->handle_scope_data();
+ prev_limit_ = current->limit;
+ current->limit = current->next;
+ prev_level_ = current->level;
+ current->level = 0;
+}
+
+
+SealHandleScope::~SealHandleScope() {
+ i::HandleScopeData* current = isolate_->handle_scope_data();
+ DCHECK_EQ(0, current->level);
+ current->level = prev_level_;
+ DCHECK_EQ(current->next, current->limit);
+ current->limit = prev_limit_;
+}
+
+
void Context::Enter() {
i::Handle<i::Context> env = Utils::OpenHandle(this);
i::Isolate* isolate = env->GetIsolate();
Index: src/api.h
diff --git a/src/api.h b/src/api.h
index
fa8682bf572079558491ee7cba95e44e55ea73b3..7fce3e3b0a27e299e7a634ad3e947b5374df64fc
100644
--- a/src/api.h
+++ b/src/api.h
@@ -661,7 +661,7 @@ void
HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
while (!blocks_.is_empty()) {
internal::Object** block_start = blocks_.last();
internal::Object** block_limit = block_start + kHandleBlockSize;
-#ifdef DEBUG
+
// SealHandleScope may make the prev_limit to point inside the block.
if (block_start <= prev_limit && prev_limit <= block_limit) {
#ifdef ENABLE_HANDLE_ZAPPING
@@ -669,9 +669,6 @@ void
HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
#endif
break;
}
-#else
- if (prev_limit == block_limit) break;
-#endif
blocks_.RemoveLast();
#ifdef ENABLE_HANDLE_ZAPPING
Index: test/cctest/cctest.status
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index
34cbab1dcb88d51c87deb6a956d7270c179f2a41..2fcf8a5e9da6ad06fdd89ed3b77fd75d63280eca
100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -40,6 +40,7 @@
# they don't fail then test.py has failed.
'test-serialize/TestThatAlwaysFails': [FAIL],
'test-serialize/DependentTestThatAlwaysFails': [FAIL],
+ 'test-api/SealHandleScope': [FAIL],
# This test always fails. It tests that LiveEdit causes abort when
turned off.
'test-debug/LiveEditDisabled': [FAIL],
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index
f7cbb8294d66d958ee16762a2b64c23646272e8f..18d2389409c6d97c9130bd22364895c60e21c610
100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -21900,3 +21900,35 @@ TEST(NewStringRangeError) {
}
free(buffer);
}
+
+
+TEST(SealHandleScope) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::SealHandleScope seal(isolate);
+
+ // Should fail
+ v8::Local<v8::Object> obj = v8::Object::New(isolate);
+
+ USE(ob);
+}
+
+
+TEST(SealHandleScopeNested) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handle_scope(isolate);
+ LocalContext env;
+
+ v8::SealHandleScope seal(isolate);
+
+ {
+ v8::HandleScope handle_scope(isolate);
+
+ // Should work
+ v8::Local<v8::Object> obj = v8::Object::New(isolate);
+
+ USE(ob);
+ }
+}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.