Commit 902a0592 authored by rafaelw@chromium.org's avatar rafaelw@chromium.org

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@chromium.org, rossberg
BUG=

Review URL: https://codereview.chromium.org/123523002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18501 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 480a3aeb
...@@ -91,10 +91,14 @@ var objectInfoMap = new ObservationWeakMap(observationState.objectInfoMap); ...@@ -91,10 +91,14 @@ var objectInfoMap = new ObservationWeakMap(observationState.objectInfoMap);
var notifierObjectInfoMap = var notifierObjectInfoMap =
new ObservationWeakMap(observationState.notifierObjectInfoMap); new ObservationWeakMap(observationState.notifierObjectInfoMap);
function TypeMapCreate() { function nullProtoObject() {
return { __proto__: null }; return { __proto__: null };
} }
function TypeMapCreate() {
return nullProtoObject();
}
function TypeMapAddType(typeMap, type, ignoreDuplicate) { function TypeMapAddType(typeMap, type, ignoreDuplicate) {
typeMap[type] = ignoreDuplicate ? 1 : (typeMap[type] || 0) + 1; typeMap[type] = ignoreDuplicate ? 1 : (typeMap[type] || 0) + 1;
} }
...@@ -142,11 +146,12 @@ var defaultAcceptTypes = TypeMapCreateFromList([ ...@@ -142,11 +146,12 @@ var defaultAcceptTypes = TypeMapCreateFromList([
// to the callback. An observer never changes its accept types and thus never // to the callback. An observer never changes its accept types and thus never
// needs to "normalize". // needs to "normalize".
function ObserverCreate(callback, acceptList) { function ObserverCreate(callback, acceptList) {
return IS_UNDEFINED(acceptList) ? callback : { if (IS_UNDEFINED(acceptList))
__proto__: null, return callback;
callback: callback, var observer = nullProtoObject();
accept: TypeMapCreateFromList(acceptList) observer.callback = callback;
}; observer.accept = TypeMapCreateFromList(acceptList);
return observer;
} }
function ObserverGetCallback(observer) { function ObserverGetCallback(observer) {
...@@ -162,8 +167,8 @@ function ObserverIsActive(observer, objectInfo) { ...@@ -162,8 +167,8 @@ function ObserverIsActive(observer, objectInfo) {
ObserverGetAcceptTypes(observer)); ObserverGetAcceptTypes(observer));
} }
function ObjectInfoGet(object) { function ObjectInfoGetOrCreate(object) {
var objectInfo = objectInfoMap.get(object); var objectInfo = ObjectInfoGet(object);
if (IS_UNDEFINED(objectInfo)) { if (IS_UNDEFINED(objectInfo)) {
if (!%IsJSProxy(object)) if (!%IsJSProxy(object))
%SetIsObserved(object); %SetIsObserved(object);
...@@ -180,6 +185,10 @@ function ObjectInfoGet(object) { ...@@ -180,6 +185,10 @@ function ObjectInfoGet(object) {
return objectInfo; return objectInfo;
} }
function ObjectInfoGet(object) {
return objectInfoMap.get(object);
}
function ObjectInfoGetFromNotifier(notifier) { function ObjectInfoGetFromNotifier(notifier) {
return notifierObjectInfoMap.get(notifier); return notifierObjectInfoMap.get(notifier);
} }
...@@ -212,7 +221,7 @@ function ObjectInfoNormalizeChangeObservers(objectInfo) { ...@@ -212,7 +221,7 @@ function ObjectInfoNormalizeChangeObservers(objectInfo) {
var callback = ObserverGetCallback(observer); var callback = ObserverGetCallback(observer);
var callbackInfo = CallbackInfoGet(callback); var callbackInfo = CallbackInfoGet(callback);
var priority = CallbackInfoGetPriority(callbackInfo); var priority = CallbackInfoGetPriority(callbackInfo);
objectInfo.changeObservers = { __proto__: null }; objectInfo.changeObservers = nullProtoObject();
objectInfo.changeObservers[priority] = observer; objectInfo.changeObservers[priority] = observer;
} }
} }
...@@ -243,7 +252,7 @@ function ObjectInfoRemoveObserver(objectInfo, callback) { ...@@ -243,7 +252,7 @@ function ObjectInfoRemoveObserver(objectInfo, callback) {
var callbackInfo = CallbackInfoGet(callback); var callbackInfo = CallbackInfoGet(callback);
var priority = CallbackInfoGetPriority(callbackInfo); var priority = CallbackInfoGetPriority(callbackInfo);
delete objectInfo.changeObservers[priority]; objectInfo.changeObservers[priority] = null;
} }
function ObjectInfoHasActiveObservers(objectInfo) { function ObjectInfoHasActiveObservers(objectInfo) {
...@@ -254,7 +263,8 @@ function ObjectInfoHasActiveObservers(objectInfo) { ...@@ -254,7 +263,8 @@ function ObjectInfoHasActiveObservers(objectInfo) {
return ObserverIsActive(objectInfo.changeObservers, objectInfo); return ObserverIsActive(objectInfo.changeObservers, objectInfo);
for (var priority in objectInfo.changeObservers) { for (var priority in objectInfo.changeObservers) {
if (ObserverIsActive(objectInfo.changeObservers[priority], objectInfo)) var observer = objectInfo.changeObservers[priority];
if (!IS_NULL(observer) && ObserverIsActive(observer, objectInfo))
return true; return true;
} }
...@@ -333,7 +343,7 @@ function ObjectObserve(object, callback, acceptList) { ...@@ -333,7 +343,7 @@ function ObjectObserve(object, callback, acceptList) {
if (!AcceptArgIsValid(acceptList)) if (!AcceptArgIsValid(acceptList))
throw MakeTypeError("observe_accept_invalid"); throw MakeTypeError("observe_accept_invalid");
var objectInfo = ObjectInfoGet(object); var objectInfo = ObjectInfoGetOrCreate(object);
ObjectInfoAddObserver(objectInfo, callback, acceptList); ObjectInfoAddObserver(objectInfo, callback, acceptList);
return object; return object;
} }
...@@ -344,7 +354,7 @@ function ObjectUnobserve(object, callback) { ...@@ -344,7 +354,7 @@ function ObjectUnobserve(object, callback) {
if (!IS_SPEC_FUNCTION(callback)) if (!IS_SPEC_FUNCTION(callback))
throw MakeTypeError("observe_non_function", ["unobserve"]); throw MakeTypeError("observe_non_function", ["unobserve"]);
var objectInfo = objectInfoMap.get(object); var objectInfo = ObjectInfoGet(object);
if (IS_UNDEFINED(objectInfo)) if (IS_UNDEFINED(objectInfo))
return object; return object;
...@@ -381,7 +391,7 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord, ...@@ -381,7 +391,7 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
var callbackInfo = CallbackInfoNormalize(callback); var callbackInfo = CallbackInfoNormalize(callback);
if (!observationState.pendingObservers) if (!observationState.pendingObservers)
observationState.pendingObservers = { __proto__: null }; observationState.pendingObservers = nullProtoObject();
observationState.pendingObservers[callbackInfo.priority] = callback; observationState.pendingObservers[callbackInfo.priority] = callback;
callbackInfo.push(changeRecord); callbackInfo.push(changeRecord);
%SetMicrotaskPending(true); %SetMicrotaskPending(true);
...@@ -424,25 +434,27 @@ function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord, ...@@ -424,25 +434,27 @@ function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord,
for (var priority in objectInfo.changeObservers) { for (var priority in objectInfo.changeObservers) {
var observer = objectInfo.changeObservers[priority]; var observer = objectInfo.changeObservers[priority];
if (IS_NULL(observer))
continue;
ObserverEnqueueIfActive(observer, objectInfo, changeRecord, ObserverEnqueueIfActive(observer, objectInfo, changeRecord,
needsAccessCheck); needsAccessCheck);
} }
} }
function BeginPerformSplice(array) { function BeginPerformSplice(array) {
var objectInfo = objectInfoMap.get(array); var objectInfo = ObjectInfoGet(array);
if (!IS_UNDEFINED(objectInfo)) if (!IS_UNDEFINED(objectInfo))
ObjectInfoAddPerformingType(objectInfo, 'splice'); ObjectInfoAddPerformingType(objectInfo, 'splice');
} }
function EndPerformSplice(array) { function EndPerformSplice(array) {
var objectInfo = objectInfoMap.get(array); var objectInfo = ObjectInfoGet(array);
if (!IS_UNDEFINED(objectInfo)) if (!IS_UNDEFINED(objectInfo))
ObjectInfoRemovePerformingType(objectInfo, 'splice'); ObjectInfoRemovePerformingType(objectInfo, 'splice');
} }
function EnqueueSpliceRecord(array, index, removed, addedCount) { function EnqueueSpliceRecord(array, index, removed, addedCount) {
var objectInfo = objectInfoMap.get(array); var objectInfo = ObjectInfoGet(array);
if (!ObjectInfoHasActiveObservers(objectInfo)) if (!ObjectInfoHasActiveObservers(objectInfo))
return; return;
...@@ -460,7 +472,7 @@ function EnqueueSpliceRecord(array, index, removed, addedCount) { ...@@ -460,7 +472,7 @@ function EnqueueSpliceRecord(array, index, removed, addedCount) {
} }
function NotifyChange(type, object, name, oldValue) { function NotifyChange(type, object, name, oldValue) {
var objectInfo = objectInfoMap.get(object); var objectInfo = ObjectInfoGet(object);
if (!ObjectInfoHasActiveObservers(objectInfo)) if (!ObjectInfoHasActiveObservers(objectInfo))
return; return;
...@@ -529,7 +541,7 @@ function ObjectGetNotifier(object) { ...@@ -529,7 +541,7 @@ function ObjectGetNotifier(object) {
if (ObjectIsFrozen(object)) return null; if (ObjectIsFrozen(object)) return null;
var objectInfo = ObjectInfoGet(object); var objectInfo = ObjectInfoGetOrCreate(object);
return ObjectInfoGetNotifier(objectInfo); return ObjectInfoGetNotifier(objectInfo);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment