Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: lib/compiler/implementation/compiler.dart

Issue 10854091: Revert "Start moving the JavaScript backend related code into a separate library" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | lib/compiler/implementation/emitter.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 5
6 /** 6 /**
7 * If true, print a warning for each method that was resolved, but not 7 * If true, print a warning for each method that was resolved, but not
8 * compiled. 8 * compiled.
9 */ 9 */
10 final bool REPORT_EXCESS_RESOLUTION = false; 10 final bool REPORT_EXCESS_RESOLUTION = false;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 } 44 }
45 45
46 abstract void enqueueHelpers(Enqueuer world); 46 abstract void enqueueHelpers(Enqueuer world);
47 abstract CodeBuffer codegen(WorkItem work); 47 abstract CodeBuffer codegen(WorkItem work);
48 abstract void processNativeClasses(Enqueuer world, 48 abstract void processNativeClasses(Enqueuer world,
49 Collection<LibraryElement> libraries); 49 Collection<LibraryElement> libraries);
50 abstract void assembleProgram(); 50 abstract void assembleProgram();
51 abstract List<CompilerTask> get tasks(); 51 abstract List<CompilerTask> get tasks();
52 } 52 }
53 53
54 class InvocationInfo {
55 int parameterCount;
56 List<HType> providedTypes;
57 List<Element> compiledFunctions;
58
59 InvocationInfo(List<HType> types)
60 : parameterCount = types != null ? types.length : -1,
61 providedTypes = types,
62 compiledFunctions = new List<Element>();
63
64 addCompiledFunction(FunctionElement function) =>
65 compiledFunctions.add(function);
66
67 void clearTypeInformation() => providedTypes = null;
68 bool get hasTypeInformation() => providedTypes != null;
69
70 }
71
72 class JavaScriptBackend extends Backend {
73 SsaBuilderTask builder;
74 SsaOptimizerTask optimizer;
75 SsaCodeGeneratorTask generator;
76 CodeEmitterTask emitter;
77 final Map<Element, Map<Element, HType>> fieldInitializers;
78 final Map<Element, Map<Element, HType>> fieldConstructorSetters;
79 final Map<Element, Map<Element, HType>> fieldSettersType;
80
81 final Map<SourceString, Map<Selector, InvocationInfo>> invocationInfo;
82
83 List<CompilerTask> get tasks() {
84 return <CompilerTask>[builder, optimizer, generator, emitter];
85 }
86
87 JavaScriptBackend(Compiler compiler, bool generateSourceMap)
88 : emitter = new CodeEmitterTask(compiler, generateSourceMap),
89 fieldInitializers = new Map<Element, Map<Element, HType>>(),
90 fieldConstructorSetters = new Map<Element, Map<Element, HType>>(),
91 fieldSettersType = new Map<Element, Map<Element, HType>>(),
92 invocationInfo = new Map<SourceString, Map<Selector, InvocationInfo>>(),
93 super(compiler) {
94 builder = new SsaBuilderTask(this);
95 optimizer = new SsaOptimizerTask(this);
96 generator = new SsaCodeGeneratorTask(this);
97 }
98
99 void enqueueHelpers(Enqueuer world) {
100 enqueueAllTopLevelFunctions(compiler.jsHelperLibrary, world);
101 enqueueAllTopLevelFunctions(compiler.interceptorsLibrary, world);
102 for (var helper in [const SourceString('Closure'),
103 const SourceString('ConstantMap'),
104 const SourceString('ConstantProtoMap')]) {
105 var e = compiler.findHelper(helper);
106 if (e !== null) world.registerInstantiatedClass(e);
107 }
108 }
109
110 CodeBuffer codegen(WorkItem work) {
111 HGraph graph = builder.build(work);
112 optimizer.optimize(work, graph);
113 if (work.allowSpeculativeOptimization
114 && optimizer.trySpeculativeOptimizations(work, graph)) {
115 CodeBuffer codeBuffer = generator.generateBailoutMethod(work, graph);
116 compiler.codegenWorld.addBailoutCode(work, codeBuffer);
117 optimizer.prepareForSpeculativeOptimizations(work, graph);
118 optimizer.optimize(work, graph);
119 }
120 return generator.generateMethod(work, graph);
121 }
122
123 void processNativeClasses(Enqueuer world,
124 Collection<LibraryElement> libraries) {
125 native.processNativeClasses(world, emitter, libraries);
126 }
127
128 void assembleProgram() {
129 emitter.assembleProgram();
130 }
131
132 void updateFieldInitializers(Element field, HType propagatedType) {
133 assert(field.isField());
134 assert(field.isMember());
135 Map<Element, HType> fields =
136 fieldInitializers.putIfAbsent(
137 field.getEnclosingClass(), () => new Map<Element, HType>());
138 if (!fields.containsKey(field)) {
139 fields[field] = propagatedType;
140 } else {
141 fields[field] = fields[field].union(propagatedType);
142 }
143 }
144
145 HType typeFromInitializersSoFar(Element field) {
146 assert(field.isField());
147 assert(field.isMember());
148 if (!fieldInitializers.containsKey(field.getEnclosingClass())) {
149 return HType.CONFLICTING;
150 }
151 Map<Element, HType> fields = fieldInitializers[field.getEnclosingClass()];
152 return fields[field];
153 }
154
155 void updateFieldConstructorSetters(Element field, HType type) {
156 assert(field.isField());
157 assert(field.isMember());
158 Map<Element, HType> fields =
159 fieldConstructorSetters.putIfAbsent(
160 field.getEnclosingClass(), () => new Map<Element, HType>());
161 if (!fields.containsKey(field)) {
162 fields[field] = type;
163 } else {
164 fields[field] = fields[field].union(type);
165 }
166 }
167
168 // Check if this field is set in the constructor body.
169 bool hasConstructorBodyFieldSetter(Element field) {
170 ClassElement enclosingClass = field.getEnclosingClass();
171 if (!fieldConstructorSetters.containsKey(enclosingClass)) {
172 return false;
173 }
174 return fieldConstructorSetters[enclosingClass][field] != null;
175 }
176
177 // Provide an optimistic estimate of the type of a field after construction.
178 // If the constructor body has setters for fields returns HType.UNKNOWN.
179 // This only takes the initializer lists and field assignments in the
180 // constructor body into account. The constructor body might have method calls
181 // that could alter the field.
182 HType optimisticFieldTypeAfterConstruction(Element field) {
183 assert(field.isField());
184 assert(field.isMember());
185
186 ClassElement classElement = field.getEnclosingClass();
187 if (hasConstructorBodyFieldSetter(field)) {
188 // If there are field setters but there is only constructor then the type
189 // of the field is determined by the assignments in the constructor
190 // body.
191 if (classElement.constructors.length == 1) {
192 return fieldConstructorSetters[classElement][field];
193 } else {
194 return HType.UNKNOWN;
195 }
196 } else if (fieldInitializers.containsKey(classElement)) {
197 HType type = fieldInitializers[classElement][field];
198 return type == null ? HType.CONFLICTING : type;
199 } else {
200 return HType.CONFLICTING;
201 }
202 }
203
204 void updateFieldSetters(Element field, HType type) {
205 assert(field.isField());
206 assert(field.isMember());
207 Map<Element, HType> fields =
208 fieldSettersType.putIfAbsent(
209 field.getEnclosingClass(), () => new Map<Element, HType>());
210 if (!fields.containsKey(field)) {
211 fields[field] = type;
212 } else {
213 fields[field] = fields[field].union(type);
214 }
215 }
216
217 // Returns the type that field setters are setting the field to based on what
218 // have been seen during compilation so far.
219 HType fieldSettersTypeSoFar(Element field) {
220 assert(field.isField());
221 assert(field.isMember());
222 ClassElement enclosingClass = field.getEnclosingClass();
223 if (!fieldSettersType.containsKey(enclosingClass)) {
224 return HType.CONFLICTING;
225 }
226 Map<Element, HType> fields = fieldSettersType[enclosingClass];
227 if (!fields.containsKey(field)) return HType.CONFLICTING;
228 return fields[field];
229 }
230
231 /**
232 * Register a dynamic invocation and collect the provided types for the
233 * named selector.
234 */
235 void registerDynamicInvocation(HInvokeDynamicMethod node, Selector selector) {
236 Map<Selector, InvocationInfo> invocationInfos =
237 invocationInfo.putIfAbsent(node.name,
238 () => new Map<Selector, InvocationInfo>());
239 InvocationInfo info = invocationInfos[selector];
240 if (info != null) {
241 // If we don't know anything useful about the types adding more
242 // information will not help.
243 if (!info.hasTypeInformation) return;
244
245 // Update the type information with the provided types.
246 bool typesChanged = false;
247 List<HType> types = info.providedTypes;
248 bool allUnknown = true;
249 for (int i = 0; i < types.length; i++) {
250 HType newType = types[i].union(node.inputs[i + 1].propagatedType);
251 if (newType != types[i]) {
252 typesChanged = true;
253 types[i] = newType;
254 }
255 if (types[i] != HType.UNKNOWN) allUnknown = false;
256 }
257 // If the provided types change we need to recompile all functions which
258 // have been compiled under the now invalidated assumptions.
259 if (typesChanged && info.compiledFunctions.length != 0) {
260 if (compiler.phase == Compiler.PHASE_COMPILING) {
261 info.compiledFunctions.forEach(
262 compiler.enqueuer.codegen.eagerRecompile);
263 info.compiledFunctions.clear();
264 }
265 }
266 // If all information is lost no need to keep it around.
267 if (allUnknown) info.clearTypeInformation();
268 } else {
269 // Gather the type information provided. If the types contains no useful
270 // information there is no need to actually store them.
271 bool allUnknown = true;
272 for (int i = 1; i < node.inputs.length; i++) {
273 if (node.inputs[i].propagatedType != HType.UNKNOWN) {
274 allUnknown = false;
275 break;
276 }
277 }
278 List<HType> types = null;
279 if (!allUnknown) {
280 types = new List<HType>(node.inputs.length - 1);
281 for (int i = 0; i < types.length; i++) {
282 types[i] = node.inputs[i + 1].propagatedType;
283 }
284 }
285 InvocationInfo info = new InvocationInfo(types);
286 invocationInfos[selector] = info;
287 }
288 }
289
290 /**
291 * Retreive the types of the parameters used for calling the [element]
292 * function. The types are optimistic in the sense as they are based on the
293 * possible invocations of the function seen so far. As compiling more
294 * code can invalidate this asumption the function is registered for being
295 * re-compiled if new possible invocations of this function invalidate these
296 * asumptions.
297 */
298 List<HType> optimisticParameterTypesWithRecompilationOnTypeChange(
299 FunctionElement element) {
300 Map<Selector, InvocationInfo> invocationInfos =
301 invocationInfo[element.name];
302 if (invocationInfos == null) return null;
303
304 int foundCount = 0;
305 InvocationInfo found = null;
306 invocationInfos.forEach((Selector selector, InvocationInfo info) {
307 if (selector.applies(element, compiler)) {
308 found = info;
309 foundCount++;
310 }
311 });
312
313 if (foundCount == 1 && found.hasTypeInformation) {
314 FunctionSignature signature = element.computeSignature(compiler);
315 if (signature.parameterCount == found.parameterCount) {
316 found.addCompiledFunction(element);
317 return found.providedTypes;
318 }
319 }
320 return null;
321 }
322 }
323
54 class Compiler implements DiagnosticListener { 324 class Compiler implements DiagnosticListener {
55 final Map<String, LibraryElement> libraries; 325 final Map<String, LibraryElement> libraries;
56 int nextFreeClassId = 0; 326 int nextFreeClassId = 0;
57 World world; 327 World world;
58 String assembledCode; 328 String assembledCode;
59 Namer namer; 329 Namer namer;
60 Types types; 330 Types types;
61 final bool enableTypeAssertions; 331 final bool enableTypeAssertions;
62 final bool enableUserAssertions; 332 final bool enableUserAssertions;
63 333
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 constantHandler = new ConstantHandler(this); 430 constantHandler = new ConstantHandler(this);
161 scanner = new ScannerTask(this); 431 scanner = new ScannerTask(this);
162 dietParser = new DietParserTask(this); 432 dietParser = new DietParserTask(this);
163 parser = new ParserTask(this); 433 parser = new ParserTask(this);
164 patchParser = new PatchParserTask(this); 434 patchParser = new PatchParserTask(this);
165 validator = new TreeValidatorTask(this); 435 validator = new TreeValidatorTask(this);
166 resolver = new ResolverTask(this); 436 resolver = new ResolverTask(this);
167 checker = new TypeCheckerTask(this); 437 checker = new TypeCheckerTask(this);
168 typesTask = new ti.TypesTask(this); 438 typesTask = new ti.TypesTask(this);
169 backend = emitJavascript ? 439 backend = emitJavascript ?
170 new js_backend.JavaScriptBackend(this, generateSourceMap) : 440 new JavaScriptBackend(this, generateSourceMap) :
171 new dart_backend.DartBackend(this, validateUnparse); 441 new dart_backend.DartBackend(this, validateUnparse);
172 enqueuer = new EnqueueTask(this); 442 enqueuer = new EnqueueTask(this);
173 tasks = [scanner, dietParser, parser, resolver, checker, 443 tasks = [scanner, dietParser, parser, resolver, checker,
174 typesTask, constantHandler, enqueuer]; 444 typesTask, constantHandler, enqueuer];
175 tasks.addAll(backend.tasks); 445 tasks.addAll(backend.tasks);
176 } 446 }
177 447
178 Universe get resolverWorld() => enqueuer.resolution.universe; 448 Universe get resolverWorld() => enqueuer.resolution.universe;
179 Universe get codegenWorld() => enqueuer.codegen.universe; 449 Universe get codegenWorld() => enqueuer.codegen.universe;
180 450
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 final endOffset = end.charOffset + end.slowCharCount; 1216 final endOffset = end.charOffset + end.slowCharCount;
947 1217
948 // [begin] and [end] might be the same for the same empty token. This 1218 // [begin] and [end] might be the same for the same empty token. This
949 // happens for instance when scanning '$$'. 1219 // happens for instance when scanning '$$'.
950 assert(endOffset >= beginOffset); 1220 assert(endOffset >= beginOffset);
951 return f(beginOffset, endOffset); 1221 return f(beginOffset, endOffset);
952 } 1222 }
953 1223
954 String toString() => 'SourceSpan($uri, $begin, $end)'; 1224 String toString() => 'SourceSpan($uri, $begin, $end)';
955 } 1225 }
OLDNEW
« no previous file with comments | « no previous file | lib/compiler/implementation/emitter.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698