Reviewers: rossberg, adamk,

Description:
Minor Object.observe optimizations

This patch includes the follow two minor optimizations:

1) When Object.unobserve-ing, instead of deleting from changeObservers, set the
index position to null, and null-check when iterating elsewhere
2) Isolate creation of null-proto objects inside a utility function

These former (deleting) was clearly showing up in d8 --prof traces and the later
was preventing optimization of containing functions because of non-standard
literal. Combined, on MDV construction/teardown benchmark, saves about 10%.

Note that this patch also cleans up retrieving objectInfo inside a utility
function.



R=rossberg
BUG=

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

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

Affected files (+33, -19 lines):
  M src/object-observe.js


Index: src/object-observe.js
diff --git a/src/object-observe.js b/src/object-observe.js
index dfa57b8312640bbdf972b5eb1bb15a6f7aba5894..985b1659854a4393e6ff24b2a03168517f98a508 100644
--- a/src/object-observe.js
+++ b/src/object-observe.js
@@ -91,10 +91,14 @@ var objectInfoMap = new ObservationWeakMap(observationState.objectInfoMap);
 var notifierObjectInfoMap =
     new ObservationWeakMap(observationState.notifierObjectInfoMap);

-function TypeMapCreate() {
+function nullProtoObject() {
   return { __proto__: null };
 }

+function TypeMapCreate() {
+  return nullProtoObject();
+}
+
 function TypeMapAddType(typeMap, type, ignoreDuplicate) {
   typeMap[type] = ignoreDuplicate ? 1 : (typeMap[type] || 0) + 1;
 }
@@ -142,11 +146,12 @@ var defaultAcceptTypes = TypeMapCreateFromList([
// to the callback. An observer never changes its accept types and thus never
 // needs to "normalize".
 function ObserverCreate(callback, acceptList) {
-  return IS_UNDEFINED(acceptList) ? callback : {
-    __proto__: null,
-    callback: callback,
-    accept: TypeMapCreateFromList(acceptList)
-  };
+  if (IS_UNDEFINED(acceptList))
+    return callback;
+  var observer = nullProtoObject();
+  observer.callback = callback;
+  observer.accept = TypeMapCreateFromList(acceptList);
+  return observer;
 }

 function ObserverGetCallback(observer) {
@@ -162,8 +167,8 @@ function ObserverIsActive(observer, objectInfo) {
                                ObserverGetAcceptTypes(observer));
 }

-function ObjectInfoGet(object) {
-  var objectInfo = objectInfoMap.get(object);
+function ObjectInfoGetOrCreate(object) {
+  var objectInfo = ObjectInfoGet(object);
   if (IS_UNDEFINED(objectInfo)) {
     if (!%IsJSProxy(object))
       %SetIsObserved(object);
@@ -180,6 +185,10 @@ function ObjectInfoGet(object) {
   return objectInfo;
 }

+function ObjectInfoGet(object) {
+  return objectInfoMap.get(object);
+}
+
 function ObjectInfoGetFromNotifier(notifier) {
   return notifierObjectInfoMap.get(notifier);
 }
@@ -212,7 +221,7 @@ function ObjectInfoNormalizeChangeObservers(objectInfo) {
     var callback = ObserverGetCallback(observer);
     var callbackInfo = CallbackInfoGet(callback);
     var priority = CallbackInfoGetPriority(callbackInfo);
-    objectInfo.changeObservers = { __proto__: null };
+    objectInfo.changeObservers = nullProtoObject();
     objectInfo.changeObservers[priority] = observer;
   }
 }
@@ -243,7 +252,7 @@ function ObjectInfoRemoveObserver(objectInfo, callback) {

   var callbackInfo = CallbackInfoGet(callback);
   var priority = CallbackInfoGetPriority(callbackInfo);
-  delete objectInfo.changeObservers[priority];
+  objectInfo.changeObservers[priority] = null;
 }

 function ObjectInfoHasActiveObservers(objectInfo) {
@@ -254,7 +263,10 @@ function ObjectInfoHasActiveObservers(objectInfo) {
     return ObserverIsActive(objectInfo.changeObservers, objectInfo);

   for (var priority in objectInfo.changeObservers) {
-    if (ObserverIsActive(objectInfo.changeObservers[priority], objectInfo))
+    var observer = objectInfo.changeObservers[priority];
+    if (!observer)
+      continue;
+    if (ObserverIsActive(observer, objectInfo))
       return true;
   }

@@ -333,7 +345,7 @@ function ObjectObserve(object, callback, acceptList) {
   if (!AcceptArgIsValid(acceptList))
     throw MakeTypeError("observe_accept_invalid");

-  var objectInfo = ObjectInfoGet(object);
+  var objectInfo = ObjectInfoGetOrCreate(object);
   ObjectInfoAddObserver(objectInfo, callback, acceptList);
   return object;
 }
@@ -344,7 +356,7 @@ function ObjectUnobserve(object, callback) {
   if (!IS_SPEC_FUNCTION(callback))
     throw MakeTypeError("observe_non_function", ["unobserve"]);

-  var objectInfo = objectInfoMap.get(object);
+  var objectInfo = ObjectInfoGet(object);
   if (IS_UNDEFINED(objectInfo))
     return object;

@@ -381,7 +393,7 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord,

   var callbackInfo = CallbackInfoNormalize(callback);
   if (!observationState.pendingObservers)
-    observationState.pendingObservers = { __proto__: null };
+    observationState.pendingObservers = nullProtoObject();
   observationState.pendingObservers[callbackInfo.priority] = callback;
   callbackInfo.push(changeRecord);
   %SetMicrotaskPending(true);
@@ -424,25 +436,27 @@ function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord,

   for (var priority in objectInfo.changeObservers) {
     var observer = objectInfo.changeObservers[priority];
+    if (!observer)
+      continue;
     ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
                             needsAccessCheck);
   }
 }

 function BeginPerformSplice(array) {
-  var objectInfo = objectInfoMap.get(array);
+  var objectInfo = ObjectInfoGet(array);
   if (!IS_UNDEFINED(objectInfo))
     ObjectInfoAddPerformingType(objectInfo, 'splice');
 }

 function EndPerformSplice(array) {
-  var objectInfo = objectInfoMap.get(array);
+  var objectInfo = ObjectInfoGet(array);
   if (!IS_UNDEFINED(objectInfo))
     ObjectInfoRemovePerformingType(objectInfo, 'splice');
 }

 function EnqueueSpliceRecord(array, index, removed, addedCount) {
-  var objectInfo = objectInfoMap.get(array);
+  var objectInfo = ObjectInfoGet(array);
   if (!ObjectInfoHasActiveObservers(objectInfo))
     return;

@@ -460,7 +474,7 @@ function EnqueueSpliceRecord(array, index, removed, addedCount) {
 }

 function NotifyChange(type, object, name, oldValue) {
-  var objectInfo = objectInfoMap.get(object);
+  var objectInfo = ObjectInfoGet(object);
   if (!ObjectInfoHasActiveObservers(objectInfo))
     return;

@@ -529,7 +543,7 @@ function ObjectGetNotifier(object) {

   if (ObjectIsFrozen(object)) return null;

-  var objectInfo = ObjectInfoGet(object);
+  var objectInfo = ObjectInfoGetOrCreate(object);
   return ObjectInfoGetNotifier(objectInfo);
 }



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