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.