Cache function proxies. This ensures that we forward invocations to the original send port.

Review URL: https://chromiumcodereview.appspot.com//10876084

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@11410 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
vsm@google.com 2012-08-27 20:21:37 +00:00
parent 618ff29a6d
commit 47e90c2a71
4 changed files with 148 additions and 11 deletions

View file

@ -86,8 +86,13 @@ function ReceivePortSync() {
} else if (message instanceof DartSendPortSync) {
return [ 'sendport', 'dart', message.isolateId, message.portId ];
} else if (message instanceof Function) {
return [ 'funcref', functionRefTable.makeRef(message),
doSerialize(functionRefTable.sendPort) ];
// In case we are reserializing a previously serialized
// function, use a cached value.
if (message._dart_serialized) return message._dart_serialized;
message._dart_serialized = [ 'funcref',
functionRefTable.makeRef(message),
doSerialize(functionRefTable.sendPort) ];
return message._dart_serialized;
} else if (message instanceof HTMLElement) {
var id = elementId(message);
// Verify that the element is connected to the document.
@ -180,7 +185,10 @@ function ReceivePortSync() {
var sendPort = deserializeSendPort(message[2]);
// Number of arguments is not used as of now
// we cannot find it out for Dart function in pure Dart.
return _makeFunctionFromRef(ref, sendPort);
var result = _makeFunctionFromRef(ref, sendPort);
// Cache the serialized form in case we resend this.
result._dart_serialized = message;
return result;
}
function deserializeProxy(message) {
@ -324,7 +332,7 @@ function ReceivePortSync() {
FunctionRefTable.prototype = new RefTable('func-ref');
FunctionRefTable.prototype.initialize = function () {
map = this.map;
var map = this.map;
this.port.receive(function (message) {
var id = message[0];
var args = message[1];
@ -341,7 +349,7 @@ function ReceivePortSync() {
JSRefTable.prototype = new RefTable('js-ref');
JSRefTable.prototype.initialize = function () {
map = this.map;
var map = this.map;
this.port.receive(function (message) {
// TODO(vsm): Support a mechanism to register a handler here.
var receiver = map[message[0]];
@ -384,14 +392,20 @@ function ReceivePortSync() {
// Leaking implementation.
// TODO(vsm): provide proper, backend-specific implementation.
function _makeFunctionFromRef(ref, sendPort) {
// If the sendPort is local, just return the underlying function.
// Otherwise, create a new function that forwards to the remote
// port.
if (sendPort instanceof LocalSendPortSync) {
return functionRefTable.map[ref];
}
return function() {
return sendPort.callSync([ref, Array.prototype.slice.call(arguments)]);
}
};
}
var localNextElementId = 0;
var _DART_ID = 'data-dart_id';
function elementId(e) {
if (e.hasAttribute(_DART_ID)) return e.getAttribute(_DART_ID);
var id = (localNextElementId++).toString();
@ -406,6 +420,6 @@ function ReceivePortSync() {
if (list.length == 0) {
throw 'Element must be attached to the document: ' + id;
}
return list[0];
return list[0];
}
})();

View file

@ -37737,6 +37737,11 @@ class _JsSerializer extends _Serializer {
}
visitFunction(Function func) {
// Look for a cached serialization first. The cached version
// should point to the original port.
var serialized = _deserializedFunctionTable.find(func);
if (serialized != null) return serialized;
// Create a new serialization forwarding to this port.
return [ 'funcref',
_functionRegistry._add(func),
visitSendPortSync(_functionRegistry._sendPort), null ];
@ -37833,6 +37838,34 @@ _deserialize(var message) {
return new _JsDeserializer().deserialize(message);
}
// TODO(vsm): Replace this with a hash map once functions are
// hashable.
class _DeserializedFunctionTable {
List data;
_DeserializedFunctionTable() {
data = [];
}
find(Function f) {
for (var item in data) {
if (f == item[0]) return item[1];
}
return null;
}
add(Function f, x) {
data.add([f, x]);
}
}
_DeserializedFunctionTable __deserializedFunctionTable = null;
get _deserializedFunctionTable {
if (__deserializedFunctionTable == null) {
__deserializedFunctionTable = new _DeserializedFunctionTable();
}
return __deserializedFunctionTable;
}
class _JsDeserializer extends _Deserializer {
static const _UNSPECIFIED = const Object();
@ -37864,9 +37897,15 @@ class _JsDeserializer extends _Deserializer {
deserializeFunction(List x) {
var id = x[1];
// If the sendPort is local, just return the underlying function.
// Otherwise, create a new function that forwards to the remote
// port.
SendPortSync port = deserializeSendPort(x[2]);
if (port is _LocalSendPortSync) {
return _functionRegistry._get(id);
}
// TODO: Support varargs when there is support in the language.
return ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
var f = ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
arg2 = _UNSPECIFIED, arg3 = _UNSPECIFIED]) {
var args = [arg0, arg1, arg2, arg3];
var last = args.indexOf(_UNSPECIFIED);
@ -37874,6 +37913,8 @@ class _JsDeserializer extends _Deserializer {
var message = [id, args];
return port.callSync(message);
};
_deserializedFunctionTable.add(f, x);
return f;
}
deserializeProxy(x) {

View file

@ -40842,6 +40842,11 @@ class _JsSerializer extends _Serializer {
}
visitFunction(Function func) {
// Look for a cached serialization first. The cached version
// should point to the original port.
var serialized = _deserializedFunctionTable.find(func);
if (serialized != null) return serialized;
// Create a new serialization forwarding to this port.
return [ 'funcref',
_functionRegistry._add(func),
visitSendPortSync(_functionRegistry._sendPort), null ];
@ -40938,6 +40943,34 @@ _deserialize(var message) {
return new _JsDeserializer().deserialize(message);
}
// TODO(vsm): Replace this with a hash map once functions are
// hashable.
class _DeserializedFunctionTable {
List data;
_DeserializedFunctionTable() {
data = [];
}
find(Function f) {
for (var item in data) {
if (f == item[0]) return item[1];
}
return null;
}
add(Function f, x) {
data.add([f, x]);
}
}
_DeserializedFunctionTable __deserializedFunctionTable = null;
get _deserializedFunctionTable {
if (__deserializedFunctionTable == null) {
__deserializedFunctionTable = new _DeserializedFunctionTable();
}
return __deserializedFunctionTable;
}
class _JsDeserializer extends _Deserializer {
static const _UNSPECIFIED = const Object();
@ -40969,9 +41002,15 @@ class _JsDeserializer extends _Deserializer {
deserializeFunction(List x) {
var id = x[1];
// If the sendPort is local, just return the underlying function.
// Otherwise, create a new function that forwards to the remote
// port.
SendPortSync port = deserializeSendPort(x[2]);
if (port is _LocalSendPortSync) {
return _functionRegistry._get(id);
}
// TODO: Support varargs when there is support in the language.
return ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
var f = ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
arg2 = _UNSPECIFIED, arg3 = _UNSPECIFIED]) {
var args = [arg0, arg1, arg2, arg3];
var last = args.indexOf(_UNSPECIFIED);
@ -40979,6 +41018,8 @@ class _JsDeserializer extends _Deserializer {
var message = [id, args];
return port.callSync(message);
};
_deserializedFunctionTable.add(f, x);
return f;
}
deserializeProxy(x) {

View file

@ -78,6 +78,11 @@ class _JsSerializer extends _Serializer {
}
visitFunction(Function func) {
// Look for a cached serialization first. The cached version
// should point to the original port.
var serialized = _deserializedFunctionTable.find(func);
if (serialized != null) return serialized;
// Create a new serialization forwarding to this port.
return [ 'funcref',
_functionRegistry._add(func),
visitSendPortSync(_functionRegistry._sendPort), null ];
@ -174,6 +179,34 @@ _deserialize(var message) {
return new _JsDeserializer().deserialize(message);
}
// TODO(vsm): Replace this with a hash map once functions are
// hashable.
class _DeserializedFunctionTable {
List data;
_DeserializedFunctionTable() {
data = [];
}
find(Function f) {
for (var item in data) {
if (f == item[0]) return item[1];
}
return null;
}
add(Function f, x) {
data.add([f, x]);
}
}
_DeserializedFunctionTable __deserializedFunctionTable = null;
get _deserializedFunctionTable {
if (__deserializedFunctionTable == null) {
__deserializedFunctionTable = new _DeserializedFunctionTable();
}
return __deserializedFunctionTable;
}
class _JsDeserializer extends _Deserializer {
static const _UNSPECIFIED = const Object();
@ -205,9 +238,15 @@ class _JsDeserializer extends _Deserializer {
deserializeFunction(List x) {
var id = x[1];
// If the sendPort is local, just return the underlying function.
// Otherwise, create a new function that forwards to the remote
// port.
SendPortSync port = deserializeSendPort(x[2]);
if (port is _LocalSendPortSync) {
return _functionRegistry._get(id);
}
// TODO: Support varargs when there is support in the language.
return ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
var f = ([arg0 = _UNSPECIFIED, arg1 = _UNSPECIFIED,
arg2 = _UNSPECIFIED, arg3 = _UNSPECIFIED]) {
var args = [arg0, arg1, arg2, arg3];
var last = args.indexOf(_UNSPECIFIED);
@ -215,6 +254,8 @@ class _JsDeserializer extends _Deserializer {
var message = [id, args];
return port.callSync(message);
};
_deserializedFunctionTable.add(f, x);
return f;
}
deserializeProxy(x) {