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 dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 class NativeGenerator { | 7 class NativeGenerator { |
8 | |
9 static bool needsIsolateAffinityTagInitialization(JavaScriptBackend backend) { | 8 static bool needsIsolateAffinityTagInitialization(JavaScriptBackend backend) { |
10 return backend.needToInitializeIsolateAffinityTag; | 9 return backend.needToInitializeIsolateAffinityTag; |
11 } | 10 } |
12 | 11 |
13 /// Generates the code for isolate affinity tags. | 12 /// Generates the code for isolate affinity tags. |
14 /// | 13 /// |
15 /// Independently Dart programs on the same page must not interfer and | 14 /// Independently Dart programs on the same page must not interfer and |
16 /// this code sets up the variables needed to guarantee that behavior. | 15 /// this code sets up the variables needed to guarantee that behavior. |
17 static jsAst.Statement generateIsolateAffinityTagInitialization( | 16 static jsAst.Statement generateIsolateAffinityTagInitialization( |
18 JavaScriptBackend backend, | 17 JavaScriptBackend backend, |
19 jsAst.Expression generateEmbeddedGlobalAccess(String global), | 18 jsAst.Expression generateEmbeddedGlobalAccess(String global), |
20 jsAst.Expression internStringFunction) { | 19 jsAst.Expression internStringFunction) { |
21 assert(backend.needToInitializeIsolateAffinityTag); | 20 assert(backend.needToInitializeIsolateAffinityTag); |
22 | 21 |
23 jsAst.Expression getIsolateTagAccess = | 22 jsAst.Expression getIsolateTagAccess = |
24 generateEmbeddedGlobalAccess(embeddedNames.GET_ISOLATE_TAG); | 23 generateEmbeddedGlobalAccess(embeddedNames.GET_ISOLATE_TAG); |
25 jsAst.Expression isolateTagAccess = | 24 jsAst.Expression isolateTagAccess = |
26 generateEmbeddedGlobalAccess(embeddedNames.ISOLATE_TAG); | 25 generateEmbeddedGlobalAccess(embeddedNames.ISOLATE_TAG); |
27 jsAst.Expression dispatchPropertyNameAccess = | 26 jsAst.Expression dispatchPropertyNameAccess = |
28 generateEmbeddedGlobalAccess(embeddedNames.DISPATCH_PROPERTY_NAME); | 27 generateEmbeddedGlobalAccess(embeddedNames.DISPATCH_PROPERTY_NAME); |
29 | 28 |
30 return js.statement(''' | 29 return js.statement( |
| 30 ''' |
31 !function() { | 31 !function() { |
32 var intern = #internStringFunction; | 32 var intern = #internStringFunction; |
33 | 33 |
34 #getIsolateTag = function(name) { | 34 #getIsolateTag = function(name) { |
35 return intern("___dart_" + name + #isolateTag); | 35 return intern("___dart_" + name + #isolateTag); |
36 }; | 36 }; |
37 | 37 |
38 // To ensure that different programs loaded into the same context (page) | 38 // To ensure that different programs loaded into the same context (page) |
39 // use distinct dispatch properies, we place an object on `Object` to | 39 // use distinct dispatch properies, we place an object on `Object` to |
40 // contain the names already in use. | 40 // contain the names already in use. |
41 var tableProperty = "___dart_isolate_tags_"; | 41 var tableProperty = "___dart_isolate_tags_"; |
42 var usedProperties = Object[tableProperty] || | 42 var usedProperties = Object[tableProperty] || |
43 (Object[tableProperty] = Object.create(null)); | 43 (Object[tableProperty] = Object.create(null)); |
44 | 44 |
45 var rootProperty = "_${generateIsolateTagRoot()}"; | 45 var rootProperty = "_${generateIsolateTagRoot()}"; |
46 for (var i = 0; ; i++) { | 46 for (var i = 0; ; i++) { |
47 var property = intern(rootProperty + "_" + i + "_"); | 47 var property = intern(rootProperty + "_" + i + "_"); |
48 if (!(property in usedProperties)) { | 48 if (!(property in usedProperties)) { |
49 usedProperties[property] = 1; | 49 usedProperties[property] = 1; |
50 #isolateTag = property; | 50 #isolateTag = property; |
51 break; | 51 break; |
52 } | 52 } |
53 } | 53 } |
54 if (#initializeDispatchProperty) { | 54 if (#initializeDispatchProperty) { |
55 #dispatchPropertyName = #getIsolateTag("dispatch_record"); | 55 #dispatchPropertyName = #getIsolateTag("dispatch_record"); |
56 } | 56 } |
57 }(); | 57 }(); |
58 ''', | 58 ''', |
59 {'initializeDispatchProperty': backend.needToInitializeDispatchProperty, | 59 { |
60 'internStringFunction': internStringFunction, | 60 'initializeDispatchProperty': |
61 'getIsolateTag': getIsolateTagAccess, | 61 backend.needToInitializeDispatchProperty, |
62 'isolateTag': isolateTagAccess, | 62 'internStringFunction': internStringFunction, |
63 'dispatchPropertyName': dispatchPropertyNameAccess}); | 63 'getIsolateTag': getIsolateTagAccess, |
| 64 'isolateTag': isolateTagAccess, |
| 65 'dispatchPropertyName': dispatchPropertyNameAccess |
| 66 }); |
64 } | 67 } |
65 | 68 |
66 static String generateIsolateTagRoot() { | 69 static String generateIsolateTagRoot() { |
67 // TODO(sra): MD5 of contributing source code or URIs? | 70 // TODO(sra): MD5 of contributing source code or URIs? |
68 return 'ZxYxX'; | 71 return 'ZxYxX'; |
69 } | 72 } |
70 | 73 |
71 /// Encodes the collected native information so that it can be treated by | 74 /// Encodes the collected native information so that it can be treated by |
72 /// the native info-handler below. | 75 /// the native info-handler below. |
73 /// | 76 /// |
74 /// The encoded information has the form: | 77 /// The encoded information has the form: |
75 /// | 78 /// |
76 // "%": "leafTag1|leafTag2|...;nonleafTag1|...;Class1|Class2|...", | 79 // "%": "leafTag1|leafTag2|...;nonleafTag1|...;Class1|Class2|...", |
77 // | 80 // |
78 // If there is no data following a semicolon, the semicolon can be omitted. | 81 // If there is no data following a semicolon, the semicolon can be omitted. |
79 static jsAst.Expression encodeNativeInfo(Class cls) { | 82 static jsAst.Expression encodeNativeInfo(Class cls) { |
80 List<String> leafTags = cls.nativeLeafTags; | 83 List<String> leafTags = cls.nativeLeafTags; |
81 List<String> nonLeafTags = cls.nativeNonLeafTags; | 84 List<String> nonLeafTags = cls.nativeNonLeafTags; |
82 List<Class> extensions = cls.nativeExtensions; | 85 List<Class> extensions = cls.nativeExtensions; |
83 | 86 |
84 String formatTags(Iterable<String> tags) { | 87 String formatTags(Iterable<String> tags) { |
85 if (tags == null) return ''; | 88 if (tags == null) return ''; |
86 return (tags.toList() | 89 return (tags.toList()..sort()).join('|'); |
87 ..sort()).join('|'); | |
88 } | 90 } |
89 | 91 |
90 String leafStr = formatTags(leafTags); | 92 String leafStr = formatTags(leafTags); |
91 String nonLeafStr = formatTags(nonLeafTags); | 93 String nonLeafStr = formatTags(nonLeafTags); |
92 | 94 |
93 StringBuffer sb = new StringBuffer(leafStr); | 95 StringBuffer sb = new StringBuffer(leafStr); |
94 if (nonLeafStr != '') { | 96 if (nonLeafStr != '') { |
95 sb | 97 sb..write(';')..write(nonLeafStr); |
96 ..write(';') | |
97 ..write(nonLeafStr); | |
98 } | 98 } |
99 | 99 |
100 String encoding = sb.toString(); | 100 String encoding = sb.toString(); |
101 | 101 |
102 if (cls.isNative || encoding != '' || extensions != null) { | 102 if (cls.isNative || encoding != '' || extensions != null) { |
103 List<jsAst.Literal> parts = <jsAst.Literal>[js.stringPart(encoding)]; | 103 List<jsAst.Literal> parts = <jsAst.Literal>[js.stringPart(encoding)]; |
104 if (extensions != null) { | 104 if (extensions != null) { |
105 parts | 105 parts |
106 ..add(js.stringPart(';')) | 106 ..add(js.stringPart(';')) |
107 ..addAll( | 107 ..addAll(js.joinLiterals( |
108 js.joinLiterals(extensions.map((Class cls) => cls.name), | 108 extensions.map((Class cls) => cls.name), js.stringPart('|'))); |
109 js.stringPart('|'))); | |
110 } | 109 } |
111 return jsAst.concatenateStrings(parts, addQuotes: true); | 110 return jsAst.concatenateStrings(parts, addQuotes: true); |
112 } | 111 } |
113 return null; | 112 return null; |
114 } | 113 } |
115 | 114 |
116 /// Returns a JavaScript template that fills the embedded globals referenced | 115 /// Returns a JavaScript template that fills the embedded globals referenced |
117 /// by [interceptorsByTagAccess] and [leafTagsAccess]. | 116 /// by [interceptorsByTagAccess] and [leafTagsAccess]. |
118 /// | 117 /// |
119 /// This code must be invoked for every class that has a native info before | 118 /// This code must be invoked for every class that has a native info before |
(...skipping 21 matching lines...) Expand all Loading... |
141 /// Both variables are passed in (instead of creating the access here) to | 140 /// Both variables are passed in (instead of creating the access here) to |
142 /// make sure the caller is aware of these globals. | 141 /// make sure the caller is aware of these globals. |
143 static jsAst.Statement buildNativeInfoHandler( | 142 static jsAst.Statement buildNativeInfoHandler( |
144 jsAst.Expression infoAccess, | 143 jsAst.Expression infoAccess, |
145 jsAst.Expression constructorAccess, | 144 jsAst.Expression constructorAccess, |
146 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass), | 145 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass), |
147 jsAst.Expression interceptorsByTagAccess, | 146 jsAst.Expression interceptorsByTagAccess, |
148 jsAst.Expression leafTagsAccess) { | 147 jsAst.Expression leafTagsAccess) { |
149 jsAst.Expression subclassRead = | 148 jsAst.Expression subclassRead = |
150 subclassReadGenerator(js('subclasses[i]', [])); | 149 subclassReadGenerator(js('subclasses[i]', [])); |
151 return js.statement(''' | 150 return js.statement( |
| 151 ''' |
152 // The native info looks like this: | 152 // The native info looks like this: |
153 // | 153 // |
154 // HtmlElement: { | 154 // HtmlElement: { |
155 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" | 155 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" |
156 // | 156 // |
157 // The first two semicolon-separated parts contain dispatch tags, the | 157 // The first two semicolon-separated parts contain dispatch tags, the |
158 // third contains the JavaScript names for classes. | 158 // third contains the JavaScript names for classes. |
159 // | 159 // |
160 // The tags indicate that JavaScript objects with the dispatch tags | 160 // The tags indicate that JavaScript objects with the dispatch tags |
161 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and | 161 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and |
(...skipping 27 matching lines...) Expand all Loading... |
189 subclass.#nativeSuperclassTagName = tags[0]; | 189 subclass.#nativeSuperclassTagName = tags[0]; |
190 } | 190 } |
191 } | 191 } |
192 for (i = 0; i < tags.length; i++) { | 192 for (i = 0; i < tags.length; i++) { |
193 #interceptorsByTagAccess[tags[i]] = #constructor; | 193 #interceptorsByTagAccess[tags[i]] = #constructor; |
194 #leafTagsAccess[tags[i]] = false; | 194 #leafTagsAccess[tags[i]] = false; |
195 } | 195 } |
196 } | 196 } |
197 } | 197 } |
198 } | 198 } |
199 ''', {'info': infoAccess, | 199 ''', |
| 200 { |
| 201 'info': infoAccess, |
200 'constructor': constructorAccess, | 202 'constructor': constructorAccess, |
201 'subclassRead': subclassRead, | 203 'subclassRead': subclassRead, |
202 'interceptorsByTagAccess': interceptorsByTagAccess, | 204 'interceptorsByTagAccess': interceptorsByTagAccess, |
203 'leafTagsAccess': leafTagsAccess, | 205 'leafTagsAccess': leafTagsAccess, |
204 'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME, | 206 'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME, |
205 'allowNativesSubclassing': true}); | 207 'allowNativesSubclassing': true |
| 208 }); |
206 } | 209 } |
207 } | 210 } |
OLD | NEW |