OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of service; | 5 part of service; |
6 | 6 |
7 /// A [ServiceObject] represents a persistent object within the vm. | 7 /// A [ServiceObject] represents a persistent object within the vm. |
8 abstract class ServiceObject extends Observable { | 8 abstract class ServiceObject extends Observable { |
9 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { | 9 static int LexicalSortName(ServiceObject o1, ServiceObject o2) { |
10 return o1.name.compareTo(o2.name); | 10 return o1.name.compareTo(o2.name); |
(...skipping 1804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1815 class FunctionKind { | 1815 class FunctionKind { |
1816 final String _strValue; | 1816 final String _strValue; |
1817 FunctionKind._internal(this._strValue); | 1817 FunctionKind._internal(this._strValue); |
1818 toString() => _strValue; | 1818 toString() => _strValue; |
1819 bool isSynthetic() => [kCollected, kNative, kStub, kTag].contains(this); | 1819 bool isSynthetic() => [kCollected, kNative, kStub, kTag].contains(this); |
1820 bool isDart() => !isSynthetic(); | 1820 bool isDart() => !isSynthetic(); |
1821 bool isStub() => (this == kStub); | 1821 bool isStub() => (this == kStub); |
1822 bool hasDartCode() => isDart() || isStub(); | 1822 bool hasDartCode() => isDart() || isStub(); |
1823 static FunctionKind fromJSON(String value) { | 1823 static FunctionKind fromJSON(String value) { |
1824 switch(value) { | 1824 switch(value) { |
1825 case 'kRegularFunction': return kRegularFunction; | 1825 case 'RegularFunction': return kRegularFunction; |
1826 case 'kClosureFunction': return kClosureFunction; | 1826 case 'ClosureFunction': return kClosureFunction; |
1827 case 'kGetterFunction': return kGetterFunction; | 1827 case 'GetterFunction': return kGetterFunction; |
1828 case 'kSetterFunction': return kSetterFunction; | 1828 case 'SetterFunction': return kSetterFunction; |
1829 case 'kConstructor': return kConstructor; | 1829 case 'Constructor': return kConstructor; |
1830 case 'kImplicitGetter': return kImplicitGetterFunction; | 1830 case 'ImplicitGetter': return kImplicitGetterFunction; |
1831 case 'kImplicitSetter': return kImplicitSetterFunction; | 1831 case 'ImplicitSetter': return kImplicitSetterFunction; |
1832 case 'kImplicitStaticFinalGetter': return kImplicitStaticFinalGetter; | 1832 case 'ImplicitStaticFinalGetter': return kImplicitStaticFinalGetter; |
1833 case 'kIrregexpFunction': return kIrregexpFunction; | 1833 case 'IrregexpFunction': return kIrregexpFunction; |
1834 case 'kStaticInitializer': return kStaticInitializer; | 1834 case 'StaticInitializer': return kStaticInitializer; |
1835 case 'kMethodExtractor': return kMethodExtractor; | 1835 case 'MethodExtractor': return kMethodExtractor; |
1836 case 'kNoSuchMethodDispatcher': return kNoSuchMethodDispatcher; | 1836 case 'NoSuchMethodDispatcher': return kNoSuchMethodDispatcher; |
1837 case 'kInvokeFieldDispatcher': return kInvokeFieldDispatcher; | 1837 case 'InvokeFieldDispatcher': return kInvokeFieldDispatcher; |
1838 case 'Collected': return kCollected; | 1838 case 'Collected': return kCollected; |
1839 case 'Native': return kNative; | 1839 case 'Native': return kNative; |
1840 case 'Stub': return kStub; | 1840 case 'Stub': return kStub; |
1841 case 'Tag': return kTag; | 1841 case 'Tag': return kTag; |
1842 } | 1842 } |
1843 Logger.root.severe('Unrecognized function kind: $value'); | 1843 Logger.root.severe('Unrecognized function kind: $value'); |
1844 throw new FallThroughError(); | 1844 throw new FallThroughError(); |
1845 } | 1845 } |
1846 | 1846 |
1847 static FunctionKind kRegularFunction = new FunctionKind._internal('function'); | 1847 static FunctionKind kRegularFunction = new FunctionKind._internal('function'); |
(...skipping 10 matching lines...) Expand all Loading... |
1858 static FunctionKind kNoSuchMethodDispatcher = new FunctionKind._internal('noSu
chMethod dispatcher'); | 1858 static FunctionKind kNoSuchMethodDispatcher = new FunctionKind._internal('noSu
chMethod dispatcher'); |
1859 static FunctionKind kInvokeFieldDispatcher = new FunctionKind._internal('invok
e field dispatcher'); | 1859 static FunctionKind kInvokeFieldDispatcher = new FunctionKind._internal('invok
e field dispatcher'); |
1860 static FunctionKind kCollected = new FunctionKind._internal('Collected'); | 1860 static FunctionKind kCollected = new FunctionKind._internal('Collected'); |
1861 static FunctionKind kNative = new FunctionKind._internal('Native'); | 1861 static FunctionKind kNative = new FunctionKind._internal('Native'); |
1862 static FunctionKind kTag = new FunctionKind._internal('Tag'); | 1862 static FunctionKind kTag = new FunctionKind._internal('Tag'); |
1863 static FunctionKind kStub = new FunctionKind._internal('Stub'); | 1863 static FunctionKind kStub = new FunctionKind._internal('Stub'); |
1864 static FunctionKind kUNKNOWN = new FunctionKind._internal('UNKNOWN'); | 1864 static FunctionKind kUNKNOWN = new FunctionKind._internal('UNKNOWN'); |
1865 } | 1865 } |
1866 | 1866 |
1867 class ServiceFunction extends ServiceObject with Coverage { | 1867 class ServiceFunction extends ServiceObject with Coverage { |
1868 @observable Class owningClass; | 1868 // owner is a Library, Class, or ServiceFunction. |
1869 @observable Library owningLibrary; | 1869 @observable ServiceObject dartOwner; |
| 1870 @observable Library library; |
1870 @observable bool isStatic; | 1871 @observable bool isStatic; |
1871 @observable bool isConst; | 1872 @observable bool isConst; |
1872 @observable ServiceFunction parent; | |
1873 @observable Script script; | 1873 @observable Script script; |
1874 @observable int tokenPos; | 1874 @observable int tokenPos; |
1875 @observable int endTokenPos; | 1875 @observable int endTokenPos; |
1876 @observable Code code; | 1876 @observable Code code; |
1877 @observable Code unoptimizedCode; | 1877 @observable Code unoptimizedCode; |
1878 @observable bool isOptimizable; | 1878 @observable bool isOptimizable; |
1879 @observable bool isInlinable; | 1879 @observable bool isInlinable; |
1880 @observable FunctionKind kind; | 1880 @observable FunctionKind kind; |
1881 @observable int deoptimizations; | 1881 @observable int deoptimizations; |
1882 @observable String qualifiedName; | 1882 @observable String qualifiedName; |
1883 @observable int usageCounter; | 1883 @observable int usageCounter; |
1884 @observable bool isDart; | 1884 @observable bool isDart; |
1885 @observable ProfileFunction profile; | 1885 @observable ProfileFunction profile; |
1886 | 1886 |
1887 bool get canCache => true; | 1887 bool get canCache => true; |
1888 bool get immutable => false; | 1888 bool get immutable => false; |
1889 | 1889 |
1890 ServiceFunction._empty(ServiceObject owner) : super._empty(owner); | 1890 ServiceFunction._empty(ServiceObject owner) : super._empty(owner); |
1891 | 1891 |
1892 void _update(ObservableMap map, bool mapIsRef) { | 1892 void _update(ObservableMap map, bool mapIsRef) { |
1893 name = map['name']; | 1893 name = map['name']; |
1894 vmName = (map.containsKey('vmName') ? map['vmName'] : name); | 1894 vmName = (map.containsKey('vmName') ? map['vmName'] : name); |
1895 | 1895 |
1896 _upgradeCollection(map, isolate); | 1896 _upgradeCollection(map, isolate); |
1897 | 1897 |
1898 owningClass = map.containsKey('owningClass') ? map['owningClass'] : null; | 1898 dartOwner = map['owner']; |
1899 owningLibrary = map.containsKey('owningLibrary') ? map['owningLibrary'] : nu
ll; | |
1900 kind = FunctionKind.fromJSON(map['kind']); | 1899 kind = FunctionKind.fromJSON(map['kind']); |
1901 isDart = !kind.isSynthetic(); | 1900 isDart = !kind.isSynthetic(); |
1902 | 1901 |
1903 if (parent == null) { | 1902 if (dartOwner is ServiceFunction) { |
1904 qualifiedName = (owningClass != null) ? | 1903 library = dartOwner.library; |
1905 "${owningClass.name}.${name}" : | 1904 qualifiedName = "${dartOwner.qualifiedName}.${name}"; |
1906 name; | 1905 |
| 1906 } else if (dartOwner is Class) { |
| 1907 library = dartOwner.library; |
| 1908 qualifiedName = "${dartOwner.name}.${name}"; |
| 1909 |
1907 } else { | 1910 } else { |
1908 qualifiedName = "${parent.qualifiedName}.${name}"; | 1911 library = dartOwner; |
| 1912 qualifiedName = name; |
1909 } | 1913 } |
1910 | 1914 |
1911 if (mapIsRef) { | 1915 if (mapIsRef) { |
1912 return; | 1916 return; |
1913 } | 1917 } |
1914 | 1918 |
1915 _loaded = true; | 1919 _loaded = true; |
1916 isStatic = map['static']; | 1920 isStatic = map['static']; |
1917 isConst = map['const']; | 1921 isConst = map['const']; |
1918 parent = map['parent']; | |
1919 script = map['script']; | 1922 script = map['script']; |
1920 tokenPos = map['tokenPos']; | 1923 tokenPos = map['tokenPos']; |
1921 endTokenPos = map['endTokenPos']; | 1924 endTokenPos = map['endTokenPos']; |
1922 code = _convertNull(map['code']); | 1925 code = map['code']; |
1923 unoptimizedCode = _convertNull(map['unoptimizedCode']); | 1926 isOptimizable = map['_optimizable']; |
1924 isOptimizable = map['optimizable']; | 1927 isInlinable = map['_inlinable']; |
1925 isInlinable = map['inlinable']; | 1928 unoptimizedCode = map['_unoptimizedCode']; |
1926 deoptimizations = map['deoptimizations']; | 1929 deoptimizations = map['_deoptimizations']; |
1927 usageCounter = map['usageCounter']; | 1930 usageCounter = map['_usageCounter']; |
1928 } | 1931 } |
1929 } | 1932 } |
1930 | 1933 |
1931 | 1934 |
1932 class Field extends ServiceObject { | 1935 class Field extends ServiceObject { |
1933 @observable var /* Library or Class */ owner; | 1936 // Library or Class. |
| 1937 @observable ServiceObject dartOwner; |
| 1938 @observable Library library; |
1934 @observable Instance declaredType; | 1939 @observable Instance declaredType; |
1935 @observable bool isStatic; | 1940 @observable bool isStatic; |
1936 @observable bool isFinal; | 1941 @observable bool isFinal; |
1937 @observable bool isConst; | 1942 @observable bool isConst; |
1938 @observable Instance value; | 1943 @observable Instance value; |
1939 @observable String name; | 1944 @observable String name; |
1940 @observable String vmName; | 1945 @observable String vmName; |
1941 | 1946 |
1942 @observable bool guardNullable; | 1947 @observable bool guardNullable; |
1943 @observable String guardClass; | 1948 @observable String guardClass; |
1944 @observable String guardLength; | 1949 @observable String guardLength; |
1945 @observable Script script; | 1950 @observable Script script; |
1946 @observable int tokenPos; | 1951 @observable int tokenPos; |
1947 | 1952 |
1948 Field._empty(ServiceObjectOwner owner) : super._empty(owner); | 1953 Field._empty(ServiceObjectOwner owner) : super._empty(owner); |
1949 | 1954 |
1950 void _update(ObservableMap map, bool mapIsRef) { | 1955 void _update(ObservableMap map, bool mapIsRef) { |
1951 // Extract full properties. | 1956 // Extract full properties. |
1952 _upgradeCollection(map, isolate); | 1957 _upgradeCollection(map, isolate); |
1953 | 1958 |
1954 name = map['name']; | 1959 name = map['name']; |
1955 vmName = (map.containsKey('vmName') ? map['vmName'] : name); | 1960 vmName = (map.containsKey('vmName') ? map['vmName'] : name); |
1956 owner = map['owner']; | 1961 dartOwner = map['owner']; |
1957 declaredType = map['declaredType']; | 1962 declaredType = map['declaredType']; |
1958 isStatic = map['static']; | 1963 isStatic = map['static']; |
1959 isFinal = map['final']; | 1964 isFinal = map['final']; |
1960 isConst = map['const']; | 1965 isConst = map['const']; |
1961 value = map['value']; | 1966 value = map['value']; |
1962 | 1967 |
| 1968 if (dartOwner is Class) { |
| 1969 library = dartOwner.library; |
| 1970 |
| 1971 } else { |
| 1972 library = dartOwner; |
| 1973 } |
| 1974 |
1963 if (mapIsRef) { | 1975 if (mapIsRef) { |
1964 return; | 1976 return; |
1965 } | 1977 } |
1966 | 1978 |
1967 guardNullable = map['guardNullable']; | 1979 guardNullable = map['_guardNullable']; |
1968 guardClass = map['guardClass']; | 1980 guardClass = map['_guardClass']; |
1969 guardLength = map['guardLength']; | 1981 guardLength = map['_guardLength']; |
1970 script = map['script']; | 1982 script = map['script']; |
1971 tokenPos = map['tokenPos']; | 1983 tokenPos = map['tokenPos']; |
1972 | 1984 |
1973 _loaded = true; | 1985 _loaded = true; |
1974 } | 1986 } |
1975 | 1987 |
1976 String toString() => 'Field(${owner.name}.$name)'; | 1988 String toString() => 'Field(${darOwner.name}.$name)'; |
1977 } | 1989 } |
1978 | 1990 |
1979 | 1991 |
1980 class ScriptLine extends Observable { | 1992 class ScriptLine extends Observable { |
1981 final Script script; | 1993 final Script script; |
1982 final int line; | 1994 final int line; |
1983 final String text; | 1995 final String text; |
1984 @observable int hits; | 1996 @observable int hits; |
1985 @observable bool possibleBpt = true; | 1997 @observable bool possibleBpt = true; |
1986 @observable bool breakpointResolved = false; | 1998 @observable bool breakpointResolved = false; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2102 String toString() => "CallSiteEntry(${receiverContainer.name}, $count)"; | 2114 String toString() => "CallSiteEntry(${receiverContainer.name}, $count)"; |
2103 } | 2115 } |
2104 | 2116 |
2105 class Script extends ServiceObject with Coverage { | 2117 class Script extends ServiceObject with Coverage { |
2106 Set<CallSite> callSites = new Set<CallSite>(); | 2118 Set<CallSite> callSites = new Set<CallSite>(); |
2107 final lines = new ObservableList<ScriptLine>(); | 2119 final lines = new ObservableList<ScriptLine>(); |
2108 final _hits = new Map<int, int>(); | 2120 final _hits = new Map<int, int>(); |
2109 @observable String kind; | 2121 @observable String kind; |
2110 @observable int firstTokenPos; | 2122 @observable int firstTokenPos; |
2111 @observable int lastTokenPos; | 2123 @observable int lastTokenPos; |
2112 @observable Library owningLibrary; | 2124 @observable Library library; |
2113 bool get canCache => true; | 2125 bool get canCache => true; |
2114 bool get immutable => true; | 2126 bool get immutable => true; |
2115 | 2127 |
2116 String _shortUrl; | 2128 String _shortUrl; |
2117 String _url; | 2129 String _url; |
2118 | 2130 |
2119 Script._empty(ServiceObjectOwner owner) : super._empty(owner); | 2131 Script._empty(ServiceObjectOwner owner) : super._empty(owner); |
2120 | 2132 |
2121 ScriptLine getLine(int line) { | 2133 ScriptLine getLine(int line) { |
2122 assert(line >= 1); | 2134 assert(line >= 1); |
(...skipping 13 matching lines...) Expand all Loading... |
2136 kind = map['kind']; | 2148 kind = map['kind']; |
2137 _url = map['name']; | 2149 _url = map['name']; |
2138 _shortUrl = _url.substring(_url.lastIndexOf('/') + 1); | 2150 _shortUrl = _url.substring(_url.lastIndexOf('/') + 1); |
2139 name = _shortUrl; | 2151 name = _shortUrl; |
2140 vmName = _url; | 2152 vmName = _url; |
2141 if (mapIsRef) { | 2153 if (mapIsRef) { |
2142 return; | 2154 return; |
2143 } | 2155 } |
2144 _parseTokenPosTable(map['tokenPosTable']); | 2156 _parseTokenPosTable(map['tokenPosTable']); |
2145 _processSource(map['source']); | 2157 _processSource(map['source']); |
2146 owningLibrary = map['owningLibrary']; | 2158 library = map['library']; |
2147 } | 2159 } |
2148 | 2160 |
2149 void _parseTokenPosTable(List<List<int>> table) { | 2161 void _parseTokenPosTable(List<List<int>> table) { |
2150 if (table == null) { | 2162 if (table == null) { |
2151 return; | 2163 return; |
2152 } | 2164 } |
2153 _tokenToLine.clear(); | 2165 _tokenToLine.clear(); |
2154 _tokenToCol.clear(); | 2166 _tokenToCol.clear(); |
2155 firstTokenPos = null; | 2167 firstTokenPos = null; |
2156 lastTokenPos = null; | 2168 lastTokenPos = null; |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2547 if (kind == CodeKind.Dart) { | 2559 if (kind == CodeKind.Dart) { |
2548 // We only reload Dart code. | 2560 // We only reload Dart code. |
2549 return super.reload(); | 2561 return super.reload(); |
2550 } | 2562 } |
2551 return new Future.value(this); | 2563 return new Future.value(this); |
2552 } | 2564 } |
2553 | 2565 |
2554 void _update(ObservableMap m, bool mapIsRef) { | 2566 void _update(ObservableMap m, bool mapIsRef) { |
2555 name = m['name']; | 2567 name = m['name']; |
2556 vmName = (m.containsKey('vmName') ? m['vmName'] : name); | 2568 vmName = (m.containsKey('vmName') ? m['vmName'] : name); |
2557 isOptimized = m['optimized'] != null ? m['optimized'] : false; | 2569 isOptimized = m['_optimized']; |
2558 kind = CodeKind.fromString(m['kind']); | 2570 kind = CodeKind.fromString(m['kind']); |
2559 startAddress = int.parse(m['start'], radix:16); | |
2560 endAddress = int.parse(m['end'], radix:16); | |
2561 function = isolate.getFromMap(m['function']); | |
2562 if (mapIsRef) { | 2571 if (mapIsRef) { |
2563 return; | 2572 return; |
2564 } | 2573 } |
2565 _loaded = true; | 2574 _loaded = true; |
2566 objectPool = isolate.getFromMap(m['objectPool']); | 2575 startAddress = int.parse(m['_startAddress'], radix:16); |
2567 var disassembly = m['disassembly']; | 2576 endAddress = int.parse(m['_endAddress'], radix:16); |
| 2577 function = isolate.getFromMap(m['function']); |
| 2578 objectPool = isolate.getFromMap(m['_objectPool']); |
| 2579 var disassembly = m['_disassembly']; |
2568 if (disassembly != null) { | 2580 if (disassembly != null) { |
2569 _processDisassembly(disassembly); | 2581 _processDisassembly(disassembly); |
2570 } | 2582 } |
2571 var descriptors = m['descriptors']; | 2583 var descriptors = m['_descriptors']; |
2572 if (descriptors != null) { | 2584 if (descriptors != null) { |
2573 descriptors = descriptors['members']; | 2585 descriptors = descriptors['members']; |
2574 _processDescriptors(descriptors); | 2586 _processDescriptors(descriptors); |
2575 } | 2587 } |
2576 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart); | 2588 hasDisassembly = (instructions.length != 0) && (kind == CodeKind.Dart); |
2577 inlinedFunctions.clear(); | 2589 inlinedFunctions.clear(); |
2578 var inlinedFunctionsTable = m['inlinedFunctions']; | 2590 var inlinedFunctionsTable = m['_inlinedFunctions']; |
2579 var inlinedIntervals = m['inlinedIntervals']; | 2591 var inlinedIntervals = m['_inlinedIntervals']; |
2580 if (inlinedFunctionsTable != null) { | 2592 if (inlinedFunctionsTable != null) { |
2581 // Iterate and upgrade each ServiceFunction. | 2593 // Iterate and upgrade each ServiceFunction. |
2582 for (var i = 0; i < inlinedFunctionsTable.length; i++) { | 2594 for (var i = 0; i < inlinedFunctionsTable.length; i++) { |
2583 // Upgrade each function and set it back in the list. | 2595 // Upgrade each function and set it back in the list. |
2584 var func = isolate.getFromMap(inlinedFunctionsTable[i]); | 2596 var func = isolate.getFromMap(inlinedFunctionsTable[i]); |
2585 inlinedFunctionsTable[i] = func; | 2597 inlinedFunctionsTable[i] = func; |
2586 if (!inlinedFunctions.contains(func)) { | 2598 if (!inlinedFunctions.contains(func)) { |
2587 inlinedFunctions.add(func); | 2599 inlinedFunctions.add(func); |
2588 } | 2600 } |
2589 } | 2601 } |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2878 void _onPoll(_) { | 2890 void _onPoll(_) { |
2879 // Reload metrics and add a sample to each. | 2891 // Reload metrics and add a sample to each. |
2880 for (var metric in metrics) { | 2892 for (var metric in metrics) { |
2881 metric.reload().then((m) { | 2893 metric.reload().then((m) { |
2882 m.addSample(new MetricSample(m.value)); | 2894 m.addSample(new MetricSample(m.value)); |
2883 }); | 2895 }); |
2884 } | 2896 } |
2885 } | 2897 } |
2886 } | 2898 } |
2887 | 2899 |
2888 // Convert any ServiceMaps representing a null instance into an actual null. | |
2889 _convertNull(obj) { | |
2890 if (obj.isNull) { | |
2891 return null; | |
2892 } | |
2893 return obj; | |
2894 } | |
2895 | |
2896 // Returns true if [map] is a service map. i.e. it has the following keys: | 2900 // Returns true if [map] is a service map. i.e. it has the following keys: |
2897 // 'id' and a 'type'. | 2901 // 'id' and a 'type'. |
2898 bool _isServiceMap(ObservableMap m) { | 2902 bool _isServiceMap(ObservableMap m) { |
2899 return (m != null) && (m['type'] != null); | 2903 return (m != null) && (m['type'] != null); |
2900 } | 2904 } |
2901 | 2905 |
2902 bool _hasRef(String type) => type.startsWith('@'); | 2906 bool _hasRef(String type) => type.startsWith('@'); |
2903 String _stripRef(String type) => (_hasRef(type) ? type.substring(1) : type); | 2907 String _stripRef(String type) => (_hasRef(type) ? type.substring(1) : type); |
2904 | 2908 |
2905 /// Recursively upgrades all [ServiceObject]s inside [collection] which must | 2909 /// Recursively upgrades all [ServiceObject]s inside [collection] which must |
(...skipping 27 matching lines...) Expand all Loading... |
2933 var v = list[i]; | 2937 var v = list[i]; |
2934 if ((v is ObservableMap) && _isServiceMap(v)) { | 2938 if ((v is ObservableMap) && _isServiceMap(v)) { |
2935 list[i] = owner.getFromMap(v); | 2939 list[i] = owner.getFromMap(v); |
2936 } else if (v is ObservableList) { | 2940 } else if (v is ObservableList) { |
2937 _upgradeObservableList(v, owner); | 2941 _upgradeObservableList(v, owner); |
2938 } else if (v is ObservableMap) { | 2942 } else if (v is ObservableMap) { |
2939 _upgradeObservableMap(v, owner); | 2943 _upgradeObservableMap(v, owner); |
2940 } | 2944 } |
2941 } | 2945 } |
2942 } | 2946 } |
OLD | NEW |