Revision: 10400
Author: [email protected]
Date: Fri Jan 13 07:14:45 2012
Log: Provide a way for iterating through all external strings
referenced from the JS heap
Review URL: http://codereview.chromium.org/9139018
http://code.google.com/p/v8/source/detail?r=10400
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/test/cctest/test-api.cc
=======================================
--- /branches/bleeding_edge/include/v8.h Tue Jan 10 08:12:16 2012
+++ /branches/bleeding_edge/include/v8.h Fri Jan 13 07:14:45 2012
@@ -2848,6 +2848,17 @@
*/
typedef bool (*EntropySource)(unsigned char* buffer, size_t length);
+
+/**
+ * Interface for iterating though all external resources in the heap.
+ */
+class V8EXPORT ExternalResourceVisitor { // NOLINT
+ public:
+ virtual ~ExternalResourceVisitor() {}
+ virtual void VisitExternalString(Handle<String> string) {}
+};
+
+
/**
* Container class for static utility functions.
*/
@@ -3203,6 +3214,13 @@
*/
static void GetHeapStatistics(HeapStatistics* heap_statistics);
+ /**
+ * Iterates through all external resources referenced from current
isolate
+ * heap. This method is not expected to be used except for debugging
purposes
+ * and may be quite slow.
+ */
+ static void VisitExternalResources(ExternalResourceVisitor* visitor);
+
/**
* Optional notification that the embedder is idle.
* V8 uses the notification to reduce memory footprint.
=======================================
--- /branches/bleeding_edge/src/api.cc Tue Jan 10 02:05:45 2012
+++ /branches/bleeding_edge/src/api.cc Fri Jan 13 07:14:45 2012
@@ -4047,6 +4047,13 @@
heap_statistics->set_used_heap_size(heap->SizeOfObjects());
heap_statistics->set_heap_size_limit(heap->MaxReserved());
}
+
+
+void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::V8::VisitExternalResources");
+ isolate->heap()->VisitExternalResources(visitor);
+}
bool v8::V8::IdleNotification(int hint) {
=======================================
--- /branches/bleeding_edge/src/heap.cc Fri Jan 13 05:09:52 2012
+++ /branches/bleeding_edge/src/heap.cc Fri Jan 13 07:14:45 2012
@@ -1352,6 +1352,28 @@
// Update the head of the list of contexts.
global_contexts_list_ = head;
}
+
+
+void Heap::VisitExternalResources(v8::ExternalResourceVisitor* visitor) {
+ AssertNoAllocation no_allocation;
+
+ class VisitorAdapter : public ObjectVisitor {
+ public:
+ explicit VisitorAdapter(v8::ExternalResourceVisitor* visitor)
+ : visitor_(visitor) {}
+ virtual void VisitPointers(Object** start, Object** end) {
+ for (Object** p = start; p < end; p++) {
+ if ((*p)->IsExternalString()) {
+ visitor_->VisitExternalString(Utils::ToLocal(
+ Handle<String>(String::cast(*p))));
+ }
+ }
+ }
+ private:
+ v8::ExternalResourceVisitor* visitor_;
+ } visitor_adapter(visitor);
+ external_string_table_.Iterate(&visitor_adapter);
+}
class NewSpaceScavenger : public StaticNewSpaceVisitor<NewSpaceScavenger> {
=======================================
--- /branches/bleeding_edge/src/heap.h Fri Jan 13 05:09:52 2012
+++ /branches/bleeding_edge/src/heap.h Fri Jan 13 07:14:45 2012
@@ -1412,6 +1412,8 @@
void ProcessWeakReferences(WeakObjectRetainer* retainer);
+ void VisitExternalResources(v8::ExternalResourceVisitor* visitor);
+
// Helper function that governs the promotion policy from new space to
// old. If the object's old address lies below the new space's age
// mark or if we've already filled the bottom 1/16th of the to space,
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Fri Jan 13 05:09:52 2012
+++ /branches/bleeding_edge/test/cctest/test-api.cc Fri Jan 13 07:14:45 2012
@@ -13673,6 +13673,59 @@
CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
}
+
+
+class VisitorImpl : public v8::ExternalResourceVisitor {
+ public:
+ VisitorImpl(TestResource* r1, TestResource* r2)
+ : resource1_(r1),
+ resource2_(r2),
+ found_resource1_(false),
+ found_resource2_(false) {}
+ virtual ~VisitorImpl() {}
+ virtual void VisitExternalString(v8::Handle<v8::String> string) {
+ if (!string->IsExternal()) {
+ CHECK(string->IsExternalAscii());
+ return;
+ }
+ v8::String::ExternalStringResource* resource =
+ string->GetExternalStringResource();
+ CHECK(resource);
+ if (resource1_ == resource) {
+ CHECK(!found_resource1_);
+ found_resource1_ = true;
+ }
+ if (resource2_ == resource) {
+ CHECK(!found_resource2_);
+ found_resource2_ = true;
+ }
+ }
+ void CheckVisitedResources() {
+ CHECK(found_resource1_);
+ CHECK(found_resource2_);
+ }
+
+ private:
+ v8::String::ExternalStringResource* resource1_;
+ v8::String::ExternalStringResource* resource2_;
+ bool found_resource1_;
+ bool found_resource2_;
+};
+
+TEST(VisitExternalStrings) {
+ v8::HandleScope scope;
+ LocalContext env;
+ const char* string = "Some string";
+ uint16_t* two_byte_string = AsciiToTwoByteString(string);
+ TestResource* resource1 = new TestResource(two_byte_string);
+ v8::Local<v8::String> string1 = v8::String::NewExternal(resource1);
+ TestResource* resource2 = new TestResource(two_byte_string);
+ v8::Local<v8::String> string2 = v8::String::NewExternal(resource2);
+
+ VisitorImpl visitor(resource1, resource2);
+ v8::V8::VisitExternalResources(&visitor);
+ visitor.CheckVisitedResources();
+}
static double DoubleFromBits(uint64_t value) {
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev