Reviewers: rossberg, Michael Starzinger,

Message:
Note that I haven't added any tests. The existing tests didn't depend on the
weakness of the maps. Suggestions on how to test that weakness welcome.

Also, note that I've put a TODO in ObservationWeakMapCreate: right now I create a new map for each JSWeakMap, which seems a little wasteful, but there are only three of them. Let me know if it's worth moving that handle to the strong roots
list now.

Description:
Object.observe: use JSWeakMaps instead of raw ObjectHashTables in observation
state

object-observe.js uses weak maps to add "hidden" properties to
objects. Previously, the hash tables it was using weren't actually
weak. This patch changes the existing runtime functions to create
instances of JSWeakMap instead of exposing ObjectHashTable directly.


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

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

Affected files:
  M src/object-observe.js
  M src/runtime.h
  M src/runtime.cc


Index: src/object-observe.js
diff --git a/src/object-observe.js b/src/object-observe.js
index d0a84f69c3eec5e45eec71043bdc52cccb829759..f30b3e4bf1ae30b353373a679f95b45ac854e8f1 100644
--- a/src/object-observe.js
+++ b/src/object-observe.js
@@ -29,33 +29,32 @@

 var observationState = %GetObservationState();
 if (IS_UNDEFINED(observationState.observerInfoMap)) {
-  observationState.observerInfoMap = %CreateObjectHashTable();
-  observationState.objectInfoMap = %CreateObjectHashTable();
-  observationState.notifierTargetMap = %CreateObjectHashTable();
+  observationState.observerInfoMap = %ObservationWeakMapCreate();
+  observationState.objectInfoMap = %ObservationWeakMapCreate();
+  observationState.notifierTargetMap = %ObservationWeakMapCreate();
   observationState.pendingObservers = new InternalArray;
   observationState.observerPriority = 0;
 }

-function InternalObjectHashTable(tableName) {
+function ObservationWeakMap(tableName) {
   this.tableName = tableName;
 }

-InternalObjectHashTable.prototype = {
+ObservationWeakMap.prototype = {
   get: function(key) {
-    return %ObjectHashTableGet(observationState[this.tableName], key);
+    return %ObservationWeakMapGet(observationState[this.tableName], key);
   },
   set: function(key, value) {
-    observationState[this.tableName] =
-        %ObjectHashTableSet(observationState[this.tableName], key, value);
+    %ObservationWeakMapSet(observationState[this.tableName], key, value);
   },
   has: function(key) {
     return !IS_UNDEFINED(this.get(key));
   }
 };

-var observerInfoMap = new InternalObjectHashTable('observerInfoMap');
-var objectInfoMap = new InternalObjectHashTable('objectInfoMap');
-var notifierTargetMap = new InternalObjectHashTable('notifierTargetMap');
+var observerInfoMap = new ObservationWeakMap('observerInfoMap');
+var objectInfoMap = new ObservationWeakMap('objectInfoMap');
+var notifierTargetMap = new ObservationWeakMap('notifierTargetMap');

 function CreateObjectInfo(object) {
   var info = {
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index e8003b6731cc77740ed36596a90a59fcfe957027..49b4731e4cb3dc19da2727a0e62baba301dffe6f 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -863,10 +863,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
 }


-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
-  HandleScope scope(isolate);
-  ASSERT(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
+static JSWeakMap* WeakMapInitialize(Isolate* isolate, Handle<JSWeakMap> weakmap) {
   ASSERT(weakmap->map()->inobject_properties() == 0);
Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
   weakmap->set_table(*table);
@@ -875,6 +872,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
 }


+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
+  return WeakMapInitialize(isolate, weakmap);
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 2);
@@ -13404,16 +13409,25 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
 }


-RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectHashTable) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
+  HandleScope scope(isolate);
   ASSERT(args.length() == 0);
-  return ObjectHashTable::Allocate(0);
+ // TODO(adamk): Currently this runtime function is only called three times per
+  // isolate. If it's called more often, the map should be moved into the
+  // strong root list.
+  Handle<Map> map =
+      isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
+  Handle<JSWeakMap> weakmap =
+      Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
+  return WeakMapInitialize(isolate, weakmap);
 }


-RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectHashTableGet) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapGet) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 2);
-  CONVERT_ARG_CHECKED(ObjectHashTable, table, 0);
+  CONVERT_ARG_CHECKED(JSWeakMap, weakmap, 0);
+  ObjectHashTable* table = ObjectHashTable::cast(weakmap->table());
   Object* key = args[1];
   if (key->IsJSGlobalProxy()) {
     key = key->GetPrototype();
@@ -13424,17 +13438,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectHashTableGet) {
 }


-RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectHashTableSet) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapSet) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 3);
-  CONVERT_ARG_HANDLE_CHECKED(ObjectHashTable, table, 0);
+  CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
+  Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
   Handle<Object> key = args.at<Object>(1);
   if (key->IsJSGlobalProxy()) {
     key = handle(key->GetPrototype(), isolate);
-    if (key->IsNull()) return *table;
+    if (key->IsNull()) return isolate->heap()->undefined_value();
   }
   Handle<Object> value = args.at<Object>(2);
-  return *PutIntoObjectHashTable(table, key, value);
+  table = PutIntoObjectHashTable(table, key, value);
+  weakmap->set_table(*table);
+  return isolate->heap()->undefined_value();
 }


Index: src/runtime.h
diff --git a/src/runtime.h b/src/runtime.h
index 0bdc81179241352dd2e71948d390d4a10b22f018..4793be85995b7a359e2331457c950a3ad76b727d 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -333,9 +333,9 @@ namespace internal {
   F(SetIsObserved, 2, 1) \
   F(SetObserverDeliveryPending, 0, 1) \
   F(GetObservationState, 0, 1) \
-  F(CreateObjectHashTable, 0, 1) \
-  F(ObjectHashTableGet, 2, 1) \
-  F(ObjectHashTableSet, 3, 1) \
+  F(ObservationWeakMapCreate, 0, 1) \
+  F(ObservationWeakMapGet, 2, 1) \
+  F(ObservationWeakMapSet, 3, 1) \
   \
   /* Statements */ \
   F(NewClosure, 3, 1) \


--
--
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/groups/opt_out.


Reply via email to