Skip to content

Instantly share code, notes, and snippets.

@indutny indutny/1.patch Secret
Created Apr 1, 2013

Embed
What would you like to do?
commit 06f5f38239d1923b481321667724503152dff7c9
Author: Fedor Indutny <fedor.indutny@gmail.com>
Date: Mon Apr 1 18:35:56 2013 +0400
External marking API for Foreign objects
diff --git a/include/v8.h b/include/v8.h
index d2b5715..fa6546f 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2031,8 +2031,14 @@ class V8EXPORT RegExp : public Object {
*/
class V8EXPORT External : public Value {
public:
+ typedef void (*MarkingCallback)(void* value);
+
static Local<External> New(void* value);
V8_INLINE(static External* Cast(Value* obj));
+
+ MarkingCallback GetMarkingCallback();
+ void SetMarkingCallback(MarkingCallback cb);
+
void* Value() const;
private:
static void CheckCast(v8::Value* obj);
diff --git a/src/api.cc b/src/api.cc
index f1fe6ea..8607f37 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -5155,6 +5155,30 @@ Local<External> v8::External::New(void* value) {
}
+External::MarkingCallback External::GetMarkingCallback() {
+ if (IsDeadCheck(i::Isolate::Current(),
+ "v8::External::GetMarkingCallback()")) {
+ return NULL;
+ }
+ i::Object* foreign = i::JSObject::cast(*Utils::OpenHandle(this))
+ ->GetInternalField(0);
+ return reinterpret_cast<External::MarkingCallback>(
+ i::Foreign::cast(foreign)->marking_callback());
+}
+
+
+void External::SetMarkingCallback(External::MarkingCallback cb) {
+ if (IsDeadCheck(i::Isolate::Current(),
+ "v8::External::SetMarkingCallback()")) {
+ return;
+ }
+ i::Object* foreign = i::JSObject::cast(*Utils::OpenHandle(this))
+ ->GetInternalField(0);
+ i::Foreign::cast(foreign)->set_marking_callback(
+ reinterpret_cast<i::Foreign::MarkingCallback>(cb));
+}
+
+
void* External::Value() const {
if (IsDeadCheck(i::Isolate::Current(), "v8::External::Value()")) return NULL;
return ExternalValue(*Utils::OpenHandle(this));
diff --git a/src/heap.cc b/src/heap.cc
index 98a530b..5285dda 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1891,6 +1891,8 @@ class ScavengingVisitor : public StaticVisitorBase {
allocation_size += kPointerSize;
}
+ Foreign::InvokeMarkingCallback(object, map);
+
Heap* heap = map->GetHeap();
if (heap->ShouldBePromoted(object->address(), object_size)) {
MaybeObject* maybe_result;
@@ -3264,6 +3266,7 @@ MaybeObject* Heap::AllocateForeign(Address address, PretenureFlag pretenure) {
MaybeObject* maybe_result = Allocate(foreign_map(), space);
if (!maybe_result->To(&result)) return maybe_result;
result->set_foreign_address(address);
+ result->set_marking_callback(NULL);
return result;
}
diff --git a/src/mark-compact-inl.h b/src/mark-compact-inl.h
index 10773e7..e595604 100644
--- a/src/mark-compact-inl.h
+++ b/src/mark-compact-inl.h
@@ -60,6 +60,9 @@ void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
ASSERT(IsMarked(obj));
ASSERT(HEAP->Contains(obj));
marking_deque_.PushBlack(obj);
+
+ // Execute marking callback for foreign objects
+ Foreign::InvokeMarkingCallback(obj, obj->map());
}
}
@@ -69,6 +72,9 @@ void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
ASSERT(Marking::MarkBitFrom(obj) == mark_bit);
mark_bit.Set();
MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size());
+
+ // Execute marking callback for foreign objects
+ Foreign::InvokeMarkingCallback(obj, obj->map());
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 61e9101..e6a1c8b 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -4969,6 +4969,30 @@ void Foreign::set_foreign_address(Address value) {
}
+inline Foreign::MarkingCallback Foreign::marking_callback() {
+ return reinterpret_cast<Foreign::MarkingCallback>(
+ AddressFrom<Address>(READ_INTPTR_FIELD(this, kForeignMarkingOffset)));
+}
+
+
+inline void Foreign::set_marking_callback(Foreign::MarkingCallback cb) {
+ WRITE_INTPTR_FIELD(this,
+ kForeignMarkingOffset,
+ OffsetFrom(reinterpret_cast<Address>(cb)));
+}
+
+
+inline void Foreign::InvokeMarkingCallback(Object* obj, Map* map) {
+ // Execute marking callback for foreign objects
+ if (map->instance_type() == FOREIGN_TYPE) {
+ Foreign* foreign = Foreign::cast(obj);
+ if (foreign->marking_callback() != NULL) {
+ foreign->marking_callback()(foreign->foreign_address());
+ }
+ }
+}
+
+
ACCESSORS(JSModule, context, Object, kContextOffset)
ACCESSORS(JSModule, scope_info, ScopeInfo, kScopeInfoOffset)
diff --git a/src/objects.h b/src/objects.h
index bd3a284..a148a52 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -8505,9 +8505,16 @@ class JSArrayBuffer: public JSObject {
// placed in old_data_space.
class Foreign: public HeapObject {
public:
+ typedef void (*MarkingCallback)(Address value);
+
// [address]: field containing the address.
inline Address foreign_address();
inline void set_foreign_address(Address value);
+ inline MarkingCallback marking_callback();
+ inline void set_marking_callback(MarkingCallback cb);
+
+ // Mark
+ static inline void InvokeMarkingCallback(Object* obj, Map* map);
// Casting.
static inline Foreign* cast(Object* obj);
@@ -8525,7 +8532,9 @@ class Foreign: public HeapObject {
// Layout description.
static const int kForeignAddressOffset = HeapObject::kHeaderSize;
- static const int kSize = kForeignAddressOffset + kPointerSize;
+ static const int kForeignMarkingOffset = HeapObject::kHeaderSize +
+ kPointerSize;
+ static const int kSize = kForeignAddressOffset + kPointerSize + kPointerSize;
STATIC_CHECK(kForeignAddressOffset == Internals::kForeignAddressOffset);
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index a9780f0..572909e 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -902,6 +902,7 @@ THREADED_TEST(FunctionTemplateSetLength) {
static void* expected_ptr;
+static int marking_called;
static v8::Handle<v8::Value> callback(const v8::Arguments& args) {
void* ptr = v8::External::Cast(*args.Data())->Value();
CHECK_EQ(expected_ptr, ptr);
@@ -909,22 +910,38 @@ static v8::Handle<v8::Value> callback(const v8::Arguments& args) {
}
+static void ExternalMarkingCallback(void* data) {
+ CHECK_EQ(expected_ptr, data);
+ marking_called++;
+}
+
+
static void TestExternalPointerWrapping() {
- LocalContext env;
+ const char* extension_list[] = { "v8/gc" };
+ v8::ExtensionConfiguration extensions(1, extension_list);
+
+ LocalContext env(&extensions);
v8::HandleScope scope(env->GetIsolate());
- v8::Handle<v8::Value> data = v8::External::New(expected_ptr);
+
+ v8::Handle<v8::External> data = v8::External::New(expected_ptr);
+
+ data->SetMarkingCallback(ExternalMarkingCallback);
v8::Handle<v8::Object> obj = v8::Object::New();
obj->Set(v8_str("func"),
v8::FunctionTemplate::New(callback, data)->GetFunction());
env->Global()->Set(v8_str("obj"), obj);
+ marking_called = 0;
CHECK(CompileRun(
"function foo() {\n"
" for (var i = 0; i < 13; i++) obj.func();\n"
+ " gc();\n"
"}\n"
"foo(), true")->BooleanValue());
+
+ CHECK_EQ(marking_called, 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.