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
This commit is contained in:
parent
480a3aeb6d
commit
902a05922b
@ -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,8 @@ 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 (!IS_NULL(observer) && ObserverIsActive(observer, objectInfo))
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -333,7 +343,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 +354,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 +391,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 +434,27 @@ function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord,
|
||||
|
||||
for (var priority in objectInfo.changeObservers) {
|
||||
var observer = objectInfo.changeObservers[priority];
|
||||
if (IS_NULL(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 +472,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 +541,7 @@ function ObjectGetNotifier(object) {
|
||||
|
||||
if (ObjectIsFrozen(object)) return null;
|
||||
|
||||
var objectInfo = ObjectInfoGet(object);
|
||||
var objectInfo = ObjectInfoGetOrCreate(object);
|
||||
return ObjectInfoGetNotifier(objectInfo);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user