Various cleanup/simplification in object-observe.js
The biggest change is the removal of the map wrapper objects: we now operate directly on the observation weak map, since there are already Get/GetOrCreate/Set functions for each info map. Various other small cleanups as well, including the deletion of unnecessary forwarding functions and making use of standard macros. R=arv@chromium.org, rossberg@chromium.org Review URL: https://codereview.chromium.org/686773002 Cr-Commit-Position: refs/heads/master@{#24972} git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24972 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
1c4f80836a
commit
a137cb74fb
@ -33,83 +33,28 @@
|
||||
// implementation of (1) and (2) have "optimized" states which represent
|
||||
// common cases which can be handled more efficiently.
|
||||
|
||||
var observationState;
|
||||
var observationState = %GetObservationState();
|
||||
|
||||
function GetObservationStateJS() {
|
||||
if (IS_UNDEFINED(observationState))
|
||||
observationState = %GetObservationState();
|
||||
|
||||
if (IS_UNDEFINED(observationState.callbackInfoMap)) {
|
||||
observationState.callbackInfoMap = %ObservationWeakMapCreate();
|
||||
observationState.objectInfoMap = %ObservationWeakMapCreate();
|
||||
observationState.notifierObjectInfoMap = %ObservationWeakMapCreate();
|
||||
observationState.pendingObservers = null;
|
||||
observationState.nextCallbackPriority = 0;
|
||||
observationState.lastMicrotaskId = 0;
|
||||
}
|
||||
|
||||
return observationState;
|
||||
}
|
||||
|
||||
function GetWeakMapWrapper() {
|
||||
function MapWrapper(map) {
|
||||
this.map_ = map;
|
||||
};
|
||||
|
||||
MapWrapper.prototype = {
|
||||
__proto__: null,
|
||||
get: function(key) {
|
||||
return %WeakCollectionGet(this.map_, key);
|
||||
},
|
||||
set: function(key, value) {
|
||||
%WeakCollectionSet(this.map_, key, value);
|
||||
},
|
||||
has: function(key) {
|
||||
return !IS_UNDEFINED(this.get(key));
|
||||
}
|
||||
};
|
||||
|
||||
return MapWrapper;
|
||||
}
|
||||
|
||||
var contextMaps;
|
||||
|
||||
function GetContextMaps() {
|
||||
if (IS_UNDEFINED(contextMaps)) {
|
||||
var map = GetWeakMapWrapper();
|
||||
var observationState = GetObservationStateJS();
|
||||
contextMaps = {
|
||||
callbackInfoMap: new map(observationState.callbackInfoMap),
|
||||
objectInfoMap: new map(observationState.objectInfoMap),
|
||||
notifierObjectInfoMap: new map(observationState.notifierObjectInfoMap)
|
||||
};
|
||||
}
|
||||
|
||||
return contextMaps;
|
||||
}
|
||||
|
||||
function GetCallbackInfoMap() {
|
||||
return GetContextMaps().callbackInfoMap;
|
||||
}
|
||||
|
||||
function GetObjectInfoMap() {
|
||||
return GetContextMaps().objectInfoMap;
|
||||
}
|
||||
|
||||
function GetNotifierObjectInfoMap() {
|
||||
return GetContextMaps().notifierObjectInfoMap;
|
||||
// This is run during the first context creation in an isolate.
|
||||
if (IS_UNDEFINED(observationState.callbackInfoMap)) {
|
||||
observationState.callbackInfoMap = %ObservationWeakMapCreate();
|
||||
observationState.objectInfoMap = %ObservationWeakMapCreate();
|
||||
observationState.notifierObjectInfoMap = %ObservationWeakMapCreate();
|
||||
observationState.pendingObservers = null;
|
||||
observationState.nextCallbackPriority = 0;
|
||||
observationState.lastMicrotaskId = 0;
|
||||
}
|
||||
|
||||
function GetPendingObservers() {
|
||||
return GetObservationStateJS().pendingObservers;
|
||||
return observationState.pendingObservers;
|
||||
}
|
||||
|
||||
function SetPendingObservers(pendingObservers) {
|
||||
GetObservationStateJS().pendingObservers = pendingObservers;
|
||||
observationState.pendingObservers = pendingObservers;
|
||||
}
|
||||
|
||||
function GetNextCallbackPriority() {
|
||||
return GetObservationStateJS().nextCallbackPriority++;
|
||||
return observationState.nextCallbackPriority++;
|
||||
}
|
||||
|
||||
function nullProtoObject() {
|
||||
@ -204,35 +149,32 @@ function ObjectInfoGetOrCreate(object) {
|
||||
performing: null,
|
||||
performingCount: 0,
|
||||
};
|
||||
GetObjectInfoMap().set(object, objectInfo);
|
||||
%WeakCollectionSet(observationState.objectInfoMap, object, objectInfo);
|
||||
}
|
||||
return objectInfo;
|
||||
}
|
||||
|
||||
function ObjectInfoGet(object) {
|
||||
return GetObjectInfoMap().get(object);
|
||||
return %WeakCollectionGet(observationState.objectInfoMap, object);
|
||||
}
|
||||
|
||||
function ObjectInfoGetFromNotifier(notifier) {
|
||||
return GetNotifierObjectInfoMap().get(notifier);
|
||||
return %WeakCollectionGet(observationState.notifierObjectInfoMap, notifier);
|
||||
}
|
||||
|
||||
function ObjectInfoGetNotifier(objectInfo) {
|
||||
if (IS_NULL(objectInfo.notifier)) {
|
||||
objectInfo.notifier = { __proto__: notifierPrototype };
|
||||
GetNotifierObjectInfoMap().set(objectInfo.notifier, objectInfo);
|
||||
%WeakCollectionSet(observationState.notifierObjectInfoMap,
|
||||
objectInfo.notifier, objectInfo);
|
||||
}
|
||||
|
||||
return objectInfo.notifier;
|
||||
}
|
||||
|
||||
function ObjectInfoGetObject(objectInfo) {
|
||||
return objectInfo.object;
|
||||
}
|
||||
|
||||
function ChangeObserversIsOptimized(changeObservers) {
|
||||
return typeof changeObservers === 'function' ||
|
||||
typeof changeObservers.callback === 'function';
|
||||
return IS_SPEC_FUNCTION(changeObservers) ||
|
||||
IS_SPEC_FUNCTION(changeObservers.callback);
|
||||
}
|
||||
|
||||
// The set of observers on an object is called 'changeObservers'. The first
|
||||
@ -328,16 +270,20 @@ function ConvertAcceptListToTypeMap(arg) {
|
||||
// priority. When a change record must be enqueued for the callback, it
|
||||
// normalizes. When delivery clears any pending change records, it re-optimizes.
|
||||
function CallbackInfoGet(callback) {
|
||||
return GetCallbackInfoMap().get(callback);
|
||||
return %WeakCollectionGet(observationState.callbackInfoMap, callback);
|
||||
}
|
||||
|
||||
function CallbackInfoSet(callback, callbackInfo) {
|
||||
%WeakCollectionSet(observationState.callbackInfoMap, callback, callbackInfo);
|
||||
}
|
||||
|
||||
function CallbackInfoGetOrCreate(callback) {
|
||||
var callbackInfo = GetCallbackInfoMap().get(callback);
|
||||
var callbackInfo = CallbackInfoGet(callback);
|
||||
if (!IS_UNDEFINED(callbackInfo))
|
||||
return callbackInfo;
|
||||
|
||||
var priority = GetNextCallbackPriority();
|
||||
GetCallbackInfoMap().set(callback, priority);
|
||||
var priority = GetNextCallbackPriority();
|
||||
CallbackInfoSet(callback, priority);
|
||||
return priority;
|
||||
}
|
||||
|
||||
@ -349,12 +295,12 @@ function CallbackInfoGetPriority(callbackInfo) {
|
||||
}
|
||||
|
||||
function CallbackInfoNormalize(callback) {
|
||||
var callbackInfo = GetCallbackInfoMap().get(callback);
|
||||
var callbackInfo = CallbackInfoGet(callback);
|
||||
if (IS_NUMBER(callbackInfo)) {
|
||||
var priority = callbackInfo;
|
||||
callbackInfo = new InternalArray;
|
||||
callbackInfo.priority = priority;
|
||||
GetCallbackInfoMap().set(callback, callbackInfo);
|
||||
CallbackInfoSet(callback, callbackInfo);
|
||||
}
|
||||
return callbackInfo;
|
||||
}
|
||||
@ -423,7 +369,7 @@ function ObserverEnqueueIfActive(observer, objectInfo, changeRecord) {
|
||||
if (IS_NULL(GetPendingObservers())) {
|
||||
SetPendingObservers(nullProtoObject());
|
||||
if (DEBUG_IS_ACTIVE) {
|
||||
var id = ++GetObservationStateJS().lastMicrotaskId;
|
||||
var id = ++observationState.lastMicrotaskId;
|
||||
var name = "Object.observe";
|
||||
%EnqueueMicrotask(function() {
|
||||
%DebugAsyncTaskEvent({ type: "willHandle", id: id, name: name });
|
||||
@ -445,8 +391,8 @@ function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) {
|
||||
|
||||
var hasType = !IS_UNDEFINED(type);
|
||||
var newRecord = hasType ?
|
||||
{ object: ObjectInfoGetObject(objectInfo), type: type } :
|
||||
{ object: ObjectInfoGetObject(objectInfo) };
|
||||
{ object: objectInfo.object, type: type } :
|
||||
{ object: objectInfo.object };
|
||||
|
||||
for (var prop in changeRecord) {
|
||||
if (prop === 'object' || (hasType && prop === 'type')) continue;
|
||||
@ -594,17 +540,18 @@ function NativeObjectGetNotifier(object) {
|
||||
}
|
||||
|
||||
function CallbackDeliverPending(callback) {
|
||||
var callbackInfo = GetCallbackInfoMap().get(callback);
|
||||
var callbackInfo = CallbackInfoGet(callback);
|
||||
if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo))
|
||||
return false;
|
||||
|
||||
// Clear the pending change records from callback and return it to its
|
||||
// "optimized" state.
|
||||
var priority = callbackInfo.priority;
|
||||
GetCallbackInfoMap().set(callback, priority);
|
||||
CallbackInfoSet(callback, priority);
|
||||
|
||||
if (GetPendingObservers())
|
||||
delete GetPendingObservers()[priority];
|
||||
var pendingObservers = GetPendingObservers();
|
||||
if (!IS_NULL(pendingObservers))
|
||||
delete pendingObservers[priority];
|
||||
|
||||
var delivered = [];
|
||||
%MoveArrayContents(callbackInfo, delivered);
|
||||
@ -624,7 +571,7 @@ function ObjectDeliverChangeRecords(callback) {
|
||||
|
||||
function ObserveMicrotaskRunner() {
|
||||
var pendingObservers = GetPendingObservers();
|
||||
if (pendingObservers) {
|
||||
if (!IS_NULL(pendingObservers)) {
|
||||
SetPendingObservers(null);
|
||||
for (var i in pendingObservers) {
|
||||
CallbackDeliverPending(pendingObservers[i]);
|
||||
|
Loading…
Reference in New Issue
Block a user