Reviewers: ulan,

Description:
Use WeakMap to handle the script wrapper cache

[email protected]
BUG=

Please review this at https://codereview.chromium.org/659513003/

Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+23, -50 lines):
  M src/factory.cc
  M src/objects.h
  M src/objects.cc
  M src/objects-inl.h
  M src/serialize.cc


Index: src/factory.cc
diff --git a/src/factory.cc b/src/factory.cc
index 5b196d3ca0aa12c03abb39cab0b220e8448d39bd..d1deb7519a23b6cddce5e2fa2d1ddeab7f1fd9e4 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -837,7 +837,6 @@ Handle<Script> Factory::NewScript(Handle<String> source) {
   heap->set_last_script_id(Smi::FromInt(id));

   // Create and initialize script object.
-  Handle<Foreign> wrapper = NewForeign(0, TENURED);
   Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE));
   script->set_source(*source);
   script->set_name(heap->undefined_value());
@@ -846,7 +845,7 @@ Handle<Script> Factory::NewScript(Handle<String> source) {
   script->set_column_offset(Smi::FromInt(0));
   script->set_context_data(heap->undefined_value());
   script->set_type(Smi::FromInt(Script::TYPE_NORMAL));
-  script->set_wrapper(*wrapper);
+  script->set_wrapper(heap->undefined_value());
   script->set_line_ends(heap->undefined_value());
   script->set_eval_from_shared(heap->undefined_value());
   script->set_eval_from_instructions_offset(Smi::FromInt(0));
Index: src/objects-inl.h
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 6385c587c5837b635ce1fc2fbd5f062bb5011d41..91bd0092244536b8293999e80640e56f9235a762 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -5407,7 +5407,7 @@ ACCESSORS(Script, id, Smi, kIdOffset)
 ACCESSORS_TO_SMI(Script, line_offset, kLineOffsetOffset)
 ACCESSORS_TO_SMI(Script, column_offset, kColumnOffsetOffset)
 ACCESSORS(Script, context_data, Object, kContextOffset)
-ACCESSORS(Script, wrapper, Foreign, kWrapperOffset)
+ACCESSORS(Script, wrapper, HeapObject, kWrapperOffset)
 ACCESSORS_TO_SMI(Script, type, kTypeOffset)
 ACCESSORS(Script, line_ends, Object, kLineEndsOffset)
 ACCESSORS(Script, eval_from_shared, Object, kEvalFromSharedOffset)
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 4f23ea58b9f1e0ef70d7f6b38fcb5ba2e6be085a..300b5b7dddfc3740ef5eff084f991ed1afe154a4 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -9727,54 +9727,27 @@ Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
 }


-// Wrappers for scripts are kept alive and cached in weak global
-// handles referred from foreign objects held by the scripts as long as
-// they are used. When they are not used anymore, the garbage
-// collector will call the weak callback on the global handle
-// associated with the wrapper and get rid of both the wrapper and the
-// handle.
-static void ClearWrapperCacheWeakCallback(
-    const v8::WeakCallbackData<v8::Value, void>& data) {
-  Object** location = reinterpret_cast<Object**>(data.GetParameter());
-  JSValue* wrapper = JSValue::cast(*location);
-  Script::cast(wrapper->value())->ClearWrapperCache();
-}
-
-
-void Script::ClearWrapperCache() {
-  Foreign* foreign = wrapper();
- Object** location = reinterpret_cast<Object**>(foreign->foreign_address()); - DCHECK_EQ(foreign->foreign_address(), reinterpret_cast<Address>(location));
-  foreign->set_foreign_address(0);
-  GlobalHandles::Destroy(location);
-  GetIsolate()->counters()->script_wrappers()->Decrement();
-}
-
-
 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
-  if (script->wrapper()->foreign_address() != NULL) {
-    // Return a handle for the existing script wrapper from the cache.
-    return Handle<JSValue>(
- *reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
-  }
   Isolate* isolate = script->GetIsolate();
+  if (!script->wrapper()->IsUndefined()) {
+    Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
+    if (!cell->value()->IsUndefined()) {
+      // Return a handle for the existing script wrapper from the cache.
+      return handle(JSObject::cast(cell->value()));
+    }
+    // If we found an empty WeakCell, that means the script wrapper was
+    // GCed.  We are not notified directly of that, so we decrement here
+    // so that we at least don't count double for any given script.
+    isolate->counters()->script_wrappers()->Decrement();
+  }
   // Construct a new script wrapper.
   isolate->counters()->script_wrappers()->Increment();
   Handle<JSFunction> constructor = isolate->script_function();
   Handle<JSValue> result =
       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
-
   result->set_value(*script);
-
-  // Create a new weak global handle and use it to cache the wrapper
-  // for future use. The cache will automatically be cleared by the
-  // garbage collector when it is not used anymore.
-  Handle<Object> handle = isolate->global_handles()->Create(*result);
-  GlobalHandles::MakeWeak(handle.location(),
-                          reinterpret_cast<void*>(handle.location()),
-                          &ClearWrapperCacheWeakCallback);
-  script->wrapper()->set_foreign_address(
-      reinterpret_cast<Address>(handle.location()));
+  Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
+  script->set_wrapper(*cell);
   return result;
 }

Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 69375570ad6a825a3ffb9ddc0e07dcdea57f9f38..5a1830408ec562076eef8aa08e60a97bb1440dfa 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -860,6 +860,7 @@ class ObjectVisitor;
 class LookupIterator;
 class StringStream;
 class TypeFeedbackVector;
+class WeakCell;
// We cannot just say "class HeapType;" if it is created from a template... =8-?
 template<class> class TypeImpl;
 struct HeapTypeConfig;
@@ -6445,8 +6446,8 @@ class Script: public Struct {
// [context_data]: context data for the context this script was compiled in.
   DECL_ACCESSORS(context_data, Object)

-  // [wrapper]: the wrapper cache.
-  DECL_ACCESSORS(wrapper, Foreign)
+  // [wrapper]: the wrapper cache.  This is either undefined or a WeakCell.
+  DECL_ACCESSORS(wrapper, HeapObject)

   // [type]: the script type.
   DECL_ACCESSORS(type, Smi)
@@ -6508,7 +6509,6 @@ class Script: public Struct {

   // Get the JS object wrapping the given script; create it if none exists.
   static Handle<JSObject> GetWrapper(Handle<Script> script);
-  void ClearWrapperCache();

   // Dispatched behavior.
   DECLARE_PRINTER(Script)
Index: src/serialize.cc
diff --git a/src/serialize.cc b/src/serialize.cc
index 70b69c23c0dc01beeda05d4bcb2532584df4b5a6..8657ea38502ac185d66741f7816ecf12299ab90e 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -2018,10 +2018,11 @@ void CodeSerializer::SerializeHeapObject(HeapObject* heap_object,
                                          HowToCode how_to_code,
                                          WhereToPoint where_to_point) {
   if (heap_object->IsScript()) {
-    // The wrapper cache uses a Foreign object to point to a global handle.
- // However, the object visitor expects foreign objects to point to external
-    // references.  Clear the cache to avoid this issue.
-    Script::cast(heap_object)->ClearWrapperCache();
+    // The wrapper cache uses a WeakCell.  However it's not clear what
+    // the semantics of WeakCell are when serializing.  For now we just
+    // clear the cache.
+    HeapObject* clear = heap_object->GetHeap()->undefined_value();
+    Script::cast(heap_object)->set_wrapper(clear);
   }

   if (FLAG_trace_code_serializer) {


--
--
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.

Reply via email to