OLD | NEW |
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 import '../constants/values.dart'; | 5 import '../constants/values.dart'; |
6 import '../elements/elements.dart'; | 6 import '../elements/elements.dart'; |
7 import '../js_backend/js_backend.dart'; | 7 import '../js_backend/js_backend.dart'; |
8 import '../js_backend/interceptor_data.dart'; | 8 import '../js_backend/interceptor_data.dart'; |
9 import '../options.dart'; | 9 import '../options.dart'; |
10 import '../types/types.dart'; | 10 import '../types/types.dart'; |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 * Instead of emitting each SSA instruction with a temporary variable | 327 * Instead of emitting each SSA instruction with a temporary variable |
328 * mark instructions that can be emitted at their use-site. | 328 * mark instructions that can be emitted at their use-site. |
329 * For example, in: | 329 * For example, in: |
330 * t0 = 4; | 330 * t0 = 4; |
331 * t1 = 3; | 331 * t1 = 3; |
332 * t2 = add(t0, t1); | 332 * t2 = add(t0, t1); |
333 * t0 and t1 would be marked and the resulting code would then be: | 333 * t0 and t1 would be marked and the resulting code would then be: |
334 * t2 = add(4, 3); | 334 * t2 = add(4, 3); |
335 */ | 335 */ |
336 class SsaInstructionMerger extends HBaseVisitor { | 336 class SsaInstructionMerger extends HBaseVisitor { |
337 final JavaScriptBackend _backend; | 337 final SuperMemberData _superMemberData; |
338 /** | 338 /** |
339 * List of [HInstruction] that the instruction merger expects in | 339 * List of [HInstruction] that the instruction merger expects in |
340 * order when visiting the inputs of an instruction. | 340 * order when visiting the inputs of an instruction. |
341 */ | 341 */ |
342 List<HInstruction> expectedInputs; | 342 List<HInstruction> expectedInputs; |
343 /** | 343 /** |
344 * Set of pure [HInstruction] that the instruction merger expects to | 344 * Set of pure [HInstruction] that the instruction merger expects to |
345 * find. The order of pure instructions do not matter, as they will | 345 * find. The order of pure instructions do not matter, as they will |
346 * not be affected by side effects. | 346 * not be affected by side effects. |
347 */ | 347 */ |
348 Set<HInstruction> pureInputs; | 348 Set<HInstruction> pureInputs; |
349 Set<HInstruction> generateAtUseSite; | 349 Set<HInstruction> generateAtUseSite; |
350 | 350 |
351 void markAsGenerateAtUseSite(HInstruction instruction) { | 351 void markAsGenerateAtUseSite(HInstruction instruction) { |
352 assert(!instruction.isJsStatement()); | 352 assert(!instruction.isJsStatement()); |
353 generateAtUseSite.add(instruction); | 353 generateAtUseSite.add(instruction); |
354 } | 354 } |
355 | 355 |
356 SsaInstructionMerger(this.generateAtUseSite, this._backend); | 356 SsaInstructionMerger(this.generateAtUseSite, this._superMemberData); |
357 | 357 |
358 void visitGraph(HGraph graph) { | 358 void visitGraph(HGraph graph) { |
359 visitDominatorTree(graph); | 359 visitDominatorTree(graph); |
360 } | 360 } |
361 | 361 |
362 void analyzeInputs(HInstruction user, int start) { | 362 void analyzeInputs(HInstruction user, int start) { |
363 List<HInstruction> inputs = user.inputs; | 363 List<HInstruction> inputs = user.inputs; |
364 for (int i = start; i < inputs.length; i++) { | 364 for (int i = start; i < inputs.length; i++) { |
365 HInstruction input = inputs[i]; | 365 HInstruction input = inputs[i]; |
366 if (!generateAtUseSite.contains(input) && | 366 if (!generateAtUseSite.contains(input) && |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 // If aliased super members cannot be used, we will generate code like | 429 // If aliased super members cannot be used, we will generate code like |
430 // | 430 // |
431 // C.prototype.method.call(instance) | 431 // C.prototype.method.call(instance) |
432 // | 432 // |
433 // where instance is the [this] object for the method. In such a case, the | 433 // where instance is the [this] object for the method. In such a case, the |
434 // get of prototype might be evaluated before instance is created if we | 434 // get of prototype might be evaluated before instance is created if we |
435 // generate instance at use site, which in turn might update the prototype | 435 // generate instance at use site, which in turn might update the prototype |
436 // after first access if we use lazy initialization. | 436 // after first access if we use lazy initialization. |
437 // In this case, we therefore don't allow the receiver (the first argument) | 437 // In this case, we therefore don't allow the receiver (the first argument) |
438 // to be generated at use site, and only analyze all other arguments. | 438 // to be generated at use site, and only analyze all other arguments. |
439 if (!_backend.canUseAliasedSuperMember(superMethod, selector)) { | 439 if (!_superMemberData.canUseAliasedSuperMember(superMethod, selector)) { |
440 analyzeInputs(instruction, 1); | 440 analyzeInputs(instruction, 1); |
441 } else { | 441 } else { |
442 super.visitInvokeSuper(instruction); | 442 super.visitInvokeSuper(instruction); |
443 } | 443 } |
444 } | 444 } |
445 | 445 |
446 void visitIs(HIs instruction) { | 446 void visitIs(HIs instruction) { |
447 // In the general case the input might be used multple multiple times, so it | 447 // In the general case the input might be used multple multiple times, so it |
448 // must not be set generate at use site. | 448 // must not be set generate at use site. |
449 | 449 |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 } | 800 } |
801 | 801 |
802 // If [thenInput] is defined in the first predecessor, then it is only used | 802 // If [thenInput] is defined in the first predecessor, then it is only used |
803 // by [phi] and can be generated at use site. | 803 // by [phi] and can be generated at use site. |
804 if (identical(thenInput.block, end.predecessors[0])) { | 804 if (identical(thenInput.block, end.predecessors[0])) { |
805 assert(thenInput.usedBy.length == 1); | 805 assert(thenInput.usedBy.length == 1); |
806 markAsGenerateAtUseSite(thenInput); | 806 markAsGenerateAtUseSite(thenInput); |
807 } | 807 } |
808 } | 808 } |
809 } | 809 } |
OLD | NEW |