Chromium Code Reviews

Unified Diff: lib/runtime/dart_runtime.js

Issue 1099333002: canonicalize const (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
« no previous file with comments | « lib/runtime/dart/typed_data.js ('k') | lib/src/codegen/js_codegen.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/runtime/dart_runtime.js
diff --git a/lib/runtime/dart_runtime.js b/lib/runtime/dart_runtime.js
index b1d2f0012055b5bea48be84451d6563f56f32f10..01791fdc06a5c9cc1c9e6bc0251e7edd0d6cdf44 100644
--- a/lib/runtime/dart_runtime.js
+++ b/lib/runtime/dart_runtime.js
@@ -11,6 +11,10 @@ var dart, _js_helper;
let getOwnPropertyNames = Object.getOwnPropertyNames;
let getOwnPropertySymbols = Object.getOwnPropertySymbols;
+ function getOwnNamesAndSymbols(obj) {
+ return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj));
+ }
+
// Adapted from Angular.js
let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
let FN_ARG_SPLIT = /,/;
@@ -24,8 +28,7 @@ var dart, _js_helper;
argDecl = fnText.match(FN_ARGS);
let r = argDecl[1].split(FN_ARG_SPLIT);
- for(let a in r) {
- let arg = r[a];
+ for (let arg of r) {
arg.replace(FN_ARG, function(all, underscore, name){
args.push(name);
});
@@ -324,14 +327,14 @@ var dart, _js_helper;
if (type instanceof AbstractFunctionType) {
if (!_isTop(type.returnType, false)) return false;
- for (var i = 0; i < type.args.length; ++i) {
+ for (let i = 0; i < type.args.length; ++i) {
if (!_isBottom(type.args[i], true)) return false;
}
- for (var i = 0; i < type.optionals.length; ++i) {
+ for (let i = 0; i < type.optionals.length; ++i) {
if (!_isBottom(type.optionals[i], true)) return false;
}
- var names = Object.getOwnPropertyNames(type.named);
- for (var i = 0; i < names.length; ++i) {
+ var names = getOwnPropertyNames(type.named);
+ for (let i = 0; i < names.length; ++i) {
if (!_isBottom(type.named[names[i]], true)) return false;
}
return true;
@@ -382,7 +385,7 @@ var dart, _js_helper;
if (this._stringValue) return this._stringValue;
var buffer = '(';
- for (var i = 0; i < this.args.length; ++i) {
+ for (let i = 0; i < this.args.length; ++i) {
if (i > 0) {
buffer += ', ';
}
@@ -391,7 +394,7 @@ var dart, _js_helper;
if (this.optionals.length > 0) {
if (this.args.length > 0) buffer += ', ';
buffer += '[';
- for (var i = 0; i < this.optionals.length; ++i) {
+ for (let i = 0; i < this.optionals.length; ++i) {
if (i > 0) {
buffer += ', ';
}
@@ -401,8 +404,8 @@ var dart, _js_helper;
} else if (this.named.length > 0) {
if (this.args.length > 0) buffer += ', ';
buffer += '{';
- let names = Object.getOwnPropertyNames(this.named).sort();
- for (var i = 0; i < names.length; ++i) {
+ let names = getOwnPropertyNames(this.named).sort();
+ for (let i = 0; i < names.length; ++i) {
if (i > 0) {
buffer += ', ';
}
@@ -523,7 +526,7 @@ var dart, _js_helper;
return false;
}
- for (var i = 0; i < args1.length; ++i) {
+ for (let i = 0; i < args1.length; ++i) {
if (!isSubtype_(args2[i], args1[i], true)) {
return false;
}
@@ -537,13 +540,13 @@ var dart, _js_helper;
}
var j = 0;
- for (var i = args1.length; i < args2.length; ++i, ++j) {
+ for (let i = args1.length; i < args2.length; ++i, ++j) {
if (!isSubtype_(args2[i], optionals1[j], true)) {
return false;
}
}
- for (var i = 0; i < optionals2.length; ++i, ++j) {
+ for (let i = 0; i < optionals2.length; ++i, ++j) {
if (!isSubtype_(optionals2[i], optionals1[j], true)) {
return false;
}
@@ -552,10 +555,10 @@ var dart, _js_helper;
let named1 = ft1.named;
let named2 = ft2.named;
- let names = Object.getOwnPropertyNames(named2);
- for (var i = 0; i < names.length; ++i) {
+ let names = getOwnPropertyNames(named2);
+ for (let i = 0; i < names.length; ++i) {
let name = names[i];
- let n1 = named1[name]
+ let n1 = named1[name];
let n2 = named2[name];
if (n1 === void 0) {
return false;
@@ -599,9 +602,7 @@ var dart, _js_helper;
}
function defineLazy(to, from) {
- let names = getOwnPropertyNames(from);
- for (let i = 0; i < names.length; i++) {
- let name = names[i];
+ for (let name of getOwnNamesAndSymbols(from)) {
defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name));
}
}
@@ -615,14 +616,9 @@ var dart, _js_helper;
* This operation is commonly called `mixin` in JS.
*/
function copyProperties(to, from) {
- function copyPropertiesHelper(names) {
- for (let i = 0; i < names.length; i++) {
- let name = names[i];
- defineProperty(to, name, getOwnPropertyDescriptor(from, name));
- }
+ for (let name of getOwnNamesAndSymbols(from)) {
+ defineProperty(to, name, getOwnPropertyDescriptor(from, name));
}
- copyPropertiesHelper(getOwnPropertyNames(from));
- copyPropertiesHelper(getOwnPropertySymbols(from));
return to;
}
dart.copyProperties = copyProperties;
@@ -716,7 +712,7 @@ var dart, _js_helper;
map.set(key, value);
}
} else if (typeof values === 'object') {
- for (let key of Object.getOwnPropertyNames(values)) {
+ for (let key of getOwnPropertyNames(values)) {
map.set(key, values[key]);
}
}
@@ -796,6 +792,59 @@ var dart, _js_helper;
}
dart.generic = generic;
+ let _value = Symbol('_value');
+ /**
+ * Looks up a sequence of [keys] in [map], recursively, and
+ * returns the result. If the value is not found, [valueFn] will be called to
+ * add it. For example:
+ *
+ * var map = new Map();
+ * putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world');
+ *
+ * ... will create a Map with a structure like:
+ *
+ * { 1: { 2: { 'hi ': { 'there ': 'world' } } } }
+ */
+ function multiKeyPutIfAbsent(map, keys, valueFn) {
+ for (let k of keys) {
+ let value = map.get(k);
+ if (!value) {
+ // TODO(jmesserly): most of these maps are very small (e.g. 1 item),
+ // so it may be worth optimizing for that.
+ map.set(k, value = new Map());
+ }
+ map = value;
+ }
+ if (map.has(_value)) return map.get(_value);
+ let value = valueFn();
+ map.set(_value, value);
+ return value;
+ }
+
+ /** The global constant table. */
+ let constants = new Map();
+
+ /**
+ * Canonicalize a constant object.
+ *
+ * Preconditions:
+ * - `obj` is an objects or array, not a primitive.
+ * - nested values of the object are themselves already canonicalized.
+ */
+ function constant(obj) {
+ let objectKey = [getRuntimeType(obj)];
+ // There's no guarantee in JS that names/symbols are returned in the same
+ // order. We could probably get the same order if we're judicious about
+ // initializing them, but easier to not depend on that.
+ for (let name of getOwnNamesAndSymbols(obj)) {
+ // TODO(jmesserly): we can make this faster if needed.
+ objectKey.push(name);
+ objectKey.push(obj[name]);
+ }
+ return multiKeyPutIfAbsent(constants, objectKey, () => obj);
+ }
+ dart.const = constant;
+
/** Sets the runtime type of `obj` to be `type` */
function setType(obj, type) {
obj[runtimeType] = type;
« no previous file with comments | « lib/runtime/dart/typed_data.js ('k') | lib/src/codegen/js_codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine