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

Side by Side Diff: pkg/compiler/lib/src/ssa/nodes.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
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
6 import '../closure.dart'; 5 import '../closure.dart';
7 import '../common.dart'; 6 import '../common.dart';
8 import '../compiler.dart' show Compiler; 7 import '../compiler.dart' show Compiler;
9 import '../constants/constant_system.dart'; 8 import '../constants/constant_system.dart';
10 import '../constants/values.dart'; 9 import '../constants/values.dart';
11 import '../dart_types.dart'; 10 import '../dart_types.dart';
12 import '../elements/elements.dart'; 11 import '../elements/elements.dart';
13 import '../io/source_information.dart'; 12 import '../io/source_information.dart';
14 import '../js/js.dart' as js; 13 import '../js/js.dart' as js;
15 import '../js_backend/backend_helpers.dart' show BackendHelpers; 14 import '../js_backend/backend_helpers.dart' show BackendHelpers;
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 assert(instruction != list.first); 144 assert(instruction != list.first);
146 } 145 }
147 } 146 }
148 147
149 currentBlock = node; 148 currentBlock = node;
150 visitInstructionList(node); 149 visitInstructionList(node);
151 } 150 }
152 } 151 }
153 152
154 class HGraph { 153 class HGraph {
155 Element element; // Used for debug printing. 154 Element element; // Used for debug printing.
156 HBasicBlock entry; 155 HBasicBlock entry;
157 HBasicBlock exit; 156 HBasicBlock exit;
158 HThis thisInstruction; 157 HThis thisInstruction;
158
159 /// Receiver parameter, set for methods using interceptor calling convention. 159 /// Receiver parameter, set for methods using interceptor calling convention.
160 HParameterValue explicitReceiverParameter; 160 HParameterValue explicitReceiverParameter;
161 bool isRecursiveMethod = false; 161 bool isRecursiveMethod = false;
162 bool calledInLoop = false; 162 bool calledInLoop = false;
163 final List<HBasicBlock> blocks = <HBasicBlock>[]; 163 final List<HBasicBlock> blocks = <HBasicBlock>[];
164 SourceInformation sourceInformation; 164 SourceInformation sourceInformation;
165 165
166 // We canonicalize all constants used within a graph so we do not 166 // We canonicalize all constants used within a graph so we do not
167 // have to worry about them for global value numbering. 167 // have to worry about them for global value numbering.
168 Map<ConstantValue, HConstant> constants = new Map<ConstantValue, HConstant>(); 168 Map<ConstantValue, HConstant> constants = new Map<ConstantValue, HConstant>();
(...skipping 11 matching lines...) Expand all
180 blocks.add(block); 180 blocks.add(block);
181 assert(identical(blocks[id], block)); 181 assert(identical(blocks[id], block));
182 } 182 }
183 183
184 HBasicBlock addNewBlock() { 184 HBasicBlock addNewBlock() {
185 HBasicBlock result = new HBasicBlock(); 185 HBasicBlock result = new HBasicBlock();
186 addBlock(result); 186 addBlock(result);
187 return result; 187 return result;
188 } 188 }
189 189
190 HBasicBlock addNewLoopHeaderBlock(JumpTarget target, 190 HBasicBlock addNewLoopHeaderBlock(
191 List<LabelDefinition> labels) { 191 JumpTarget target, List<LabelDefinition> labels) {
192 HBasicBlock result = addNewBlock(); 192 HBasicBlock result = addNewBlock();
193 result.loopInformation = 193 result.loopInformation = new HLoopInformation(result, target, labels);
194 new HLoopInformation(result, target, labels);
195 return result; 194 return result;
196 } 195 }
197 196
198 HConstant addConstant(ConstantValue constant, Compiler compiler, 197 HConstant addConstant(ConstantValue constant, Compiler compiler,
199 {SourceInformation sourceInformation}) { 198 {SourceInformation sourceInformation}) {
200 HConstant result = constants[constant]; 199 HConstant result = constants[constant];
201 // TODO(johnniwinther): Support source information per constant reference. 200 // TODO(johnniwinther): Support source information per constant reference.
202 if (result == null) { 201 if (result == null) {
203 TypeMask type = computeTypeMask(compiler, constant); 202 TypeMask type = computeTypeMask(compiler, constant);
204 result = new HConstant.internal(constant, type) 203 result = new HConstant.internal(constant, type)
205 ..sourceInformation = sourceInformation; 204 ..sourceInformation = sourceInformation;
206 entry.addAtExit(result); 205 entry.addAtExit(result);
207 constants[constant] = result; 206 constants[constant] = result;
208 } else if (result.block == null) { 207 } else if (result.block == null) {
209 // The constant was not used anymore. 208 // The constant was not used anymore.
210 entry.addAtExit(result); 209 entry.addAtExit(result);
211 } 210 }
212 return result; 211 return result;
213 } 212 }
214 213
215 HConstant addDeferredConstant(ConstantValue constant, PrefixElement prefix, 214 HConstant addDeferredConstant(ConstantValue constant, PrefixElement prefix,
216 SourceInformation sourceInformation, 215 SourceInformation sourceInformation, Compiler compiler) {
217 Compiler compiler) {
218 // TODO(sigurdm,johnniwinter): These deferred constants should be created 216 // TODO(sigurdm,johnniwinter): These deferred constants should be created
219 // by the constant evaluator. 217 // by the constant evaluator.
220 ConstantValue wrapper = new DeferredConstantValue(constant, prefix); 218 ConstantValue wrapper = new DeferredConstantValue(constant, prefix);
221 compiler.deferredLoadTask.registerConstantDeferredUse(wrapper, prefix); 219 compiler.deferredLoadTask.registerConstantDeferredUse(wrapper, prefix);
222 return addConstant(wrapper, compiler, sourceInformation: sourceInformation); 220 return addConstant(wrapper, compiler, sourceInformation: sourceInformation);
223 } 221 }
224 222
225 HConstant addConstantInt(int i, Compiler compiler) { 223 HConstant addConstantInt(int i, Compiler compiler) {
226 return addConstant(compiler.backend.constantSystem.createInt(i), compiler); 224 return addConstant(compiler.backend.constantSystem.createInt(i), compiler);
227 } 225 }
228 226
229 HConstant addConstantDouble(double d, Compiler compiler) { 227 HConstant addConstantDouble(double d, Compiler compiler) {
230 return addConstant( 228 return addConstant(
231 compiler.backend.constantSystem.createDouble(d), compiler); 229 compiler.backend.constantSystem.createDouble(d), compiler);
232 } 230 }
233 231
234 HConstant addConstantString(ast.DartString str, 232 HConstant addConstantString(ast.DartString str, Compiler compiler) {
235 Compiler compiler) {
236 return addConstant( 233 return addConstant(
237 compiler.backend.constantSystem.createString(str), 234 compiler.backend.constantSystem.createString(str), compiler);
235 }
236
237 HConstant addConstantStringFromName(js.Name name, Compiler compiler) {
238 return addConstant(
239 new SyntheticConstantValue(
240 SyntheticConstantKind.NAME, js.quoteName(name)),
238 compiler); 241 compiler);
239 } 242 }
240 243
241 HConstant addConstantStringFromName(js.Name name,
242 Compiler compiler) {
243 return addConstant(
244 new SyntheticConstantValue(SyntheticConstantKind.NAME,
245 js.quoteName(name)),
246 compiler);
247 }
248
249 HConstant addConstantBool(bool value, Compiler compiler) { 244 HConstant addConstantBool(bool value, Compiler compiler) {
250 return addConstant( 245 return addConstant(
251 compiler.backend.constantSystem.createBool(value), compiler); 246 compiler.backend.constantSystem.createBool(value), compiler);
252 } 247 }
253 248
254 HConstant addConstantNull(Compiler compiler) { 249 HConstant addConstantNull(Compiler compiler) {
255 return addConstant(compiler.backend.constantSystem.createNull(), compiler); 250 return addConstant(compiler.backend.constantSystem.createNull(), compiler);
256 } 251 }
257 252
258 void finalize() { 253 void finalize() {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 visitForeignCode(HForeignCode node) => visitInstruction(node); 329 visitForeignCode(HForeignCode node) => visitInstruction(node);
335 visitForeignNew(HForeignNew node) => visitInstruction(node); 330 visitForeignNew(HForeignNew node) => visitInstruction(node);
336 visitGoto(HGoto node) => visitControlFlow(node); 331 visitGoto(HGoto node) => visitControlFlow(node);
337 visitGreater(HGreater node) => visitRelational(node); 332 visitGreater(HGreater node) => visitRelational(node);
338 visitGreaterEqual(HGreaterEqual node) => visitRelational(node); 333 visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
339 visitIdentity(HIdentity node) => visitRelational(node); 334 visitIdentity(HIdentity node) => visitRelational(node);
340 visitIf(HIf node) => visitConditionalBranch(node); 335 visitIf(HIf node) => visitConditionalBranch(node);
341 visitIndex(HIndex node) => visitInstruction(node); 336 visitIndex(HIndex node) => visitInstruction(node);
342 visitIndexAssign(HIndexAssign node) => visitInstruction(node); 337 visitIndexAssign(HIndexAssign node) => visitInstruction(node);
343 visitInterceptor(HInterceptor node) => visitInstruction(node); 338 visitInterceptor(HInterceptor node) => visitInstruction(node);
344 visitInvokeClosure(HInvokeClosure node) 339 visitInvokeClosure(HInvokeClosure node) => visitInvokeDynamic(node);
345 => visitInvokeDynamic(node); 340 visitInvokeConstructorBody(HInvokeConstructorBody node) =>
346 visitInvokeConstructorBody(HInvokeConstructorBody node) 341 visitInvokeStatic(node);
347 => visitInvokeStatic(node); 342 visitInvokeDynamicMethod(HInvokeDynamicMethod node) =>
348 visitInvokeDynamicMethod(HInvokeDynamicMethod node) 343 visitInvokeDynamic(node);
349 => visitInvokeDynamic(node); 344 visitInvokeDynamicGetter(HInvokeDynamicGetter node) =>
350 visitInvokeDynamicGetter(HInvokeDynamicGetter node) 345 visitInvokeDynamicField(node);
351 => visitInvokeDynamicField(node); 346 visitInvokeDynamicSetter(HInvokeDynamicSetter node) =>
352 visitInvokeDynamicSetter(HInvokeDynamicSetter node) 347 visitInvokeDynamicField(node);
353 => visitInvokeDynamicField(node);
354 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node); 348 visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
355 visitInvokeSuper(HInvokeSuper node) => visitInvokeStatic(node); 349 visitInvokeSuper(HInvokeSuper node) => visitInvokeStatic(node);
356 visitJump(HJump node) => visitControlFlow(node); 350 visitJump(HJump node) => visitControlFlow(node);
357 visitLazyStatic(HLazyStatic node) => visitInstruction(node); 351 visitLazyStatic(HLazyStatic node) => visitInstruction(node);
358 visitLess(HLess node) => visitRelational(node); 352 visitLess(HLess node) => visitRelational(node);
359 visitLessEqual(HLessEqual node) => visitRelational(node); 353 visitLessEqual(HLessEqual node) => visitRelational(node);
360 visitLiteralList(HLiteralList node) => visitInstruction(node); 354 visitLiteralList(HLiteralList node) => visitInstruction(node);
361 visitLocalAccess(HLocalAccess node) => visitInstruction(node); 355 visitLocalAccess(HLocalAccess node) => visitInstruction(node);
362 visitLocalGet(HLocalGet node) => visitLocalAccess(node); 356 visitLocalGet(HLocalGet node) => visitLocalAccess(node);
363 visitLocalSet(HLocalSet node) => visitLocalAccess(node); 357 visitLocalSet(HLocalSet node) => visitLocalAccess(node);
364 visitLocalValue(HLocalValue node) => visitInstruction(node); 358 visitLocalValue(HLocalValue node) => visitInstruction(node);
365 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node); 359 visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
366 visitNegate(HNegate node) => visitInvokeUnary(node); 360 visitNegate(HNegate node) => visitInvokeUnary(node);
367 visitNot(HNot node) => visitInstruction(node); 361 visitNot(HNot node) => visitInstruction(node);
368 visitOneShotInterceptor(HOneShotInterceptor node) 362 visitOneShotInterceptor(HOneShotInterceptor node) => visitInvokeDynamic(node);
369 => visitInvokeDynamic(node);
370 visitPhi(HPhi node) => visitInstruction(node); 363 visitPhi(HPhi node) => visitInstruction(node);
371 visitMultiply(HMultiply node) => visitBinaryArithmetic(node); 364 visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
372 visitParameterValue(HParameterValue node) => visitLocalValue(node); 365 visitParameterValue(HParameterValue node) => visitLocalValue(node);
373 visitRangeConversion(HRangeConversion node) => visitCheck(node); 366 visitRangeConversion(HRangeConversion node) => visitCheck(node);
374 visitReadModifyWrite(HReadModifyWrite node) => visitInstruction(node); 367 visitReadModifyWrite(HReadModifyWrite node) => visitInstruction(node);
375 visitRef(HRef node) => node.value.accept(this); 368 visitRef(HRef node) => node.value.accept(this);
376 visitReturn(HReturn node) => visitControlFlow(node); 369 visitReturn(HReturn node) => visitControlFlow(node);
377 visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node); 370 visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
378 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node); 371 visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
379 visitSubtract(HSubtract node) => visitBinaryArithmetic(node); 372 visitSubtract(HSubtract node) => visitBinaryArithmetic(node);
(...skipping 29 matching lines...) Expand all
409 402
410 bool contains(HBasicBlock block) { 403 bool contains(HBasicBlock block) {
411 assert(start != null); 404 assert(start != null);
412 assert(end != null); 405 assert(end != null);
413 assert(block != null); 406 assert(block != null);
414 return start.id <= block.id && block.id <= end.id; 407 return start.id <= block.id && block.id <= end.id;
415 } 408 }
416 } 409 }
417 410
418 class SubExpression extends SubGraph { 411 class SubExpression extends SubGraph {
419 const SubExpression(HBasicBlock start, HBasicBlock end) 412 const SubExpression(HBasicBlock start, HBasicBlock end) : super(start, end);
420 : super(start, end);
421 413
422 /** Find the condition expression if this sub-expression is a condition. */ 414 /** Find the condition expression if this sub-expression is a condition. */
423 HInstruction get conditionExpression { 415 HInstruction get conditionExpression {
424 HInstruction last = end.last; 416 HInstruction last = end.last;
425 if (last is HConditionalBranch || last is HSwitch) return last.inputs[0]; 417 if (last is HConditionalBranch || last is HSwitch) return last.inputs[0];
426 return null; 418 return null;
427 } 419 }
428 } 420 }
429 421
430 class HInstructionList { 422 class HInstructionList {
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 530
539 bool isLoopHeader() { 531 bool isLoopHeader() {
540 return loopInformation != null; 532 return loopInformation != null;
541 } 533 }
542 534
543 void setBlockFlow(HBlockInformation blockInfo, HBasicBlock continuation) { 535 void setBlockFlow(HBlockInformation blockInfo, HBasicBlock continuation) {
544 blockFlow = new HBlockFlow(blockInfo, continuation); 536 blockFlow = new HBlockFlow(blockInfo, continuation);
545 } 537 }
546 538
547 bool isLabeledBlock() => 539 bool isLabeledBlock() =>
548 blockFlow != null && 540 blockFlow != null && blockFlow.body is HLabeledBlockInformation;
549 blockFlow.body is HLabeledBlockInformation;
550 541
551 HBasicBlock get enclosingLoopHeader { 542 HBasicBlock get enclosingLoopHeader {
552 if (isLoopHeader()) return this; 543 if (isLoopHeader()) return this;
553 return parentLoopHeader; 544 return parentLoopHeader;
554 } 545 }
555 546
556 void open() { 547 void open() {
557 assert(isNew()); 548 assert(isNew());
558 status = STATUS_OPEN; 549 status = STATUS_OPEN;
559 } 550 }
560 551
561 void close(HControlFlow end) { 552 void close(HControlFlow end) {
562 assert(isOpen()); 553 assert(isOpen());
563 addAfter(last, end); 554 addAfter(last, end);
564 status = STATUS_CLOSED; 555 status = STATUS_CLOSED;
565 } 556 }
566 557
567 void addAtEntry(HInstruction instruction) { 558 void addAtEntry(HInstruction instruction) {
568 assert(instruction is !HPhi); 559 assert(instruction is! HPhi);
569 internalAddBefore(first, instruction); 560 internalAddBefore(first, instruction);
570 instruction.notifyAddedToBlock(this); 561 instruction.notifyAddedToBlock(this);
571 } 562 }
572 563
573 void addAtExit(HInstruction instruction) { 564 void addAtExit(HInstruction instruction) {
574 assert(isClosed()); 565 assert(isClosed());
575 assert(last is HControlFlow); 566 assert(last is HControlFlow);
576 assert(instruction is !HPhi); 567 assert(instruction is! HPhi);
577 internalAddBefore(last, instruction); 568 internalAddBefore(last, instruction);
578 instruction.notifyAddedToBlock(this); 569 instruction.notifyAddedToBlock(this);
579 } 570 }
580 571
581 void moveAtExit(HInstruction instruction) { 572 void moveAtExit(HInstruction instruction) {
582 assert(instruction is !HPhi); 573 assert(instruction is! HPhi);
583 assert(instruction.isInBasicBlock()); 574 assert(instruction.isInBasicBlock());
584 assert(isClosed()); 575 assert(isClosed());
585 assert(last is HControlFlow); 576 assert(last is HControlFlow);
586 internalAddBefore(last, instruction); 577 internalAddBefore(last, instruction);
587 instruction.block = this; 578 instruction.block = this;
588 assert(isValid()); 579 assert(isValid());
589 } 580 }
590 581
591 void add(HInstruction instruction) { 582 void add(HInstruction instruction) {
592 assert(instruction is !HControlFlow); 583 assert(instruction is! HControlFlow);
593 assert(instruction is !HPhi); 584 assert(instruction is! HPhi);
594 internalAddAfter(last, instruction); 585 internalAddAfter(last, instruction);
595 instruction.notifyAddedToBlock(this); 586 instruction.notifyAddedToBlock(this);
596 } 587 }
597 588
598 void addPhi(HPhi phi) { 589 void addPhi(HPhi phi) {
599 assert(phi.inputs.length == 0 || phi.inputs.length == predecessors.length); 590 assert(phi.inputs.length == 0 || phi.inputs.length == predecessors.length);
600 assert(phi.block == null); 591 assert(phi.block == null);
601 phis.internalAddAfter(phis.last, phi); 592 phis.internalAddAfter(phis.last, phi);
602 phi.notifyAddedToBlock(this); 593 phi.notifyAddedToBlock(this);
603 } 594 }
604 595
605 void removePhi(HPhi phi) { 596 void removePhi(HPhi phi) {
606 phis.remove(phi); 597 phis.remove(phi);
607 assert(phi.block == this); 598 assert(phi.block == this);
608 phi.notifyRemovedFromBlock(); 599 phi.notifyRemovedFromBlock();
609 } 600 }
610 601
611 void addAfter(HInstruction cursor, HInstruction instruction) { 602 void addAfter(HInstruction cursor, HInstruction instruction) {
612 assert(cursor is !HPhi); 603 assert(cursor is! HPhi);
613 assert(instruction is !HPhi); 604 assert(instruction is! HPhi);
614 assert(isOpen() || isClosed()); 605 assert(isOpen() || isClosed());
615 internalAddAfter(cursor, instruction); 606 internalAddAfter(cursor, instruction);
616 instruction.notifyAddedToBlock(this); 607 instruction.notifyAddedToBlock(this);
617 } 608 }
618 609
619 void addBefore(HInstruction cursor, HInstruction instruction) { 610 void addBefore(HInstruction cursor, HInstruction instruction) {
620 assert(cursor is !HPhi); 611 assert(cursor is! HPhi);
621 assert(instruction is !HPhi); 612 assert(instruction is! HPhi);
622 assert(isOpen() || isClosed()); 613 assert(isOpen() || isClosed());
623 internalAddBefore(cursor, instruction); 614 internalAddBefore(cursor, instruction);
624 instruction.notifyAddedToBlock(this); 615 instruction.notifyAddedToBlock(this);
625 } 616 }
626 617
627 void remove(HInstruction instruction) { 618 void remove(HInstruction instruction) {
628 assert(isOpen() || isClosed()); 619 assert(isOpen() || isClosed());
629 assert(instruction is !HPhi); 620 assert(instruction is! HPhi);
630 super.remove(instruction); 621 super.remove(instruction);
631 assert(instruction.block == this); 622 assert(instruction.block == this);
632 instruction.notifyRemovedFromBlock(); 623 instruction.notifyRemovedFromBlock();
633 } 624 }
634 625
635 void addSuccessor(HBasicBlock block) { 626 void addSuccessor(HBasicBlock block) {
636 if (successors.isEmpty) { 627 if (successors.isEmpty) {
637 successors = [block]; 628 successors = [block];
638 } else { 629 } else {
639 successors.add(block); 630 successors.add(block);
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 static const int SHIFT_RIGHT_TYPECODE = 30; 844 static const int SHIFT_RIGHT_TYPECODE = 30;
854 static const int READ_TYPE_VARIABLE_TYPECODE = 31; 845 static const int READ_TYPE_VARIABLE_TYPECODE = 31;
855 static const int FUNCTION_TYPE_TYPECODE = 32; 846 static const int FUNCTION_TYPE_TYPECODE = 32;
856 static const int VOID_TYPE_TYPECODE = 33; 847 static const int VOID_TYPE_TYPECODE = 33;
857 static const int INTERFACE_TYPE_TYPECODE = 34; 848 static const int INTERFACE_TYPE_TYPECODE = 34;
858 static const int DYNAMIC_TYPE_TYPECODE = 35; 849 static const int DYNAMIC_TYPE_TYPECODE = 35;
859 static const int TRUNCATING_DIVIDE_TYPECODE = 36; 850 static const int TRUNCATING_DIVIDE_TYPECODE = 36;
860 static const int IS_VIA_INTERCEPTOR_TYPECODE = 37; 851 static const int IS_VIA_INTERCEPTOR_TYPECODE = 37;
861 852
862 HInstruction(this.inputs, this.instructionType) 853 HInstruction(this.inputs, this.instructionType)
863 : id = idCounter++, usedBy = <HInstruction>[] { 854 : id = idCounter++,
855 usedBy = <HInstruction>[] {
864 assert(inputs.every((e) => e != null)); 856 assert(inputs.every((e) => e != null));
865 } 857 }
866 858
867 int get hashCode => id; 859 int get hashCode => id;
868 860
869 bool useGvn() => _useGvn; 861 bool useGvn() => _useGvn;
870 void setUseGvn() { _useGvn = true; } 862 void setUseGvn() {
863 _useGvn = true;
864 }
871 865
872 bool get isMovable => useGvn(); 866 bool get isMovable => useGvn();
873 867
874 /** 868 /**
875 * A pure instruction is an instruction that does not have any side 869 * A pure instruction is an instruction that does not have any side
876 * effect, nor any dependency. They can be moved anywhere in the 870 * effect, nor any dependency. They can be moved anywhere in the
877 * graph. 871 * graph.
878 */ 872 */
879 bool isPure() { 873 bool isPure() {
880 return !sideEffects.hasSideEffects() 874 return !sideEffects.hasSideEffects() &&
881 && !sideEffects.dependsOnSomething() 875 !sideEffects.dependsOnSomething() &&
882 && !canThrow(); 876 !canThrow();
883 } 877 }
884 878
885 /// An instruction is an 'allocation' is it is the sole alias for an object. 879 /// An instruction is an 'allocation' is it is the sole alias for an object.
886 /// This applies to to instructions that allocate new objects and can be 880 /// This applies to to instructions that allocate new objects and can be
887 /// extended to methods that return other allocations without escaping them. 881 /// extended to methods that return other allocations without escaping them.
888 bool get isAllocation => false; 882 bool get isAllocation => false;
889 883
890 /// Overridden by [HCheck] to return the actual non-[HCheck] 884 /// Overridden by [HCheck] to return the actual non-[HCheck]
891 /// instruction it checks against. 885 /// instruction it checks against.
892 HInstruction nonCheck() => this; 886 HInstruction nonCheck() => this;
893 887
894 /// Can this node throw an exception? 888 /// Can this node throw an exception?
895 bool canThrow() => false; 889 bool canThrow() => false;
896 890
897 /// Does this node potentially affect control flow. 891 /// Does this node potentially affect control flow.
898 bool isControlFlow() => false; 892 bool isControlFlow() => false;
899 893
900 bool isExact() => instructionType.isExact || isNull(); 894 bool isExact() => instructionType.isExact || isNull();
901 895
902 bool isValue() => instructionType.isValue; 896 bool isValue() => instructionType.isValue;
903 897
904 bool canBeNull() => instructionType.isNullable; 898 bool canBeNull() => instructionType.isNullable;
905 899
906 bool isNull() => instructionType.isNull; 900 bool isNull() => instructionType.isNull;
907 901
908 bool isConflicting() => instructionType.isEmpty; 902 bool isConflicting() => instructionType.isEmpty;
909 903
910 /// Returns `true` if [typeMask] contains [cls]. 904 /// Returns `true` if [typeMask] contains [cls].
911 static bool containsType( 905 static bool containsType(
912 TypeMask typeMask, 906 TypeMask typeMask, ClassElement cls, ClassWorld classWorld) {
913 ClassElement cls,
914 ClassWorld classWorld) {
915 return classWorld.isInstantiated(cls) && typeMask.contains(cls, classWorld); 907 return classWorld.isInstantiated(cls) && typeMask.contains(cls, classWorld);
916 } 908 }
917 909
918 /// Returns `true` if [typeMask] contains only [cls]. 910 /// Returns `true` if [typeMask] contains only [cls].
919 static bool containsOnlyType( 911 static bool containsOnlyType(
920 TypeMask typeMask, 912 TypeMask typeMask, ClassElement cls, ClassWorld classWorld) {
921 ClassElement cls, 913 return classWorld.isInstantiated(cls) && typeMask.containsOnly(cls);
922 ClassWorld classWorld) {
923 return classWorld.isInstantiated(cls) &&
924 typeMask.containsOnly(cls);
925 } 914 }
926 915
927 /// Returns `true` if [typeMask] is an instance of [cls]. 916 /// Returns `true` if [typeMask] is an instance of [cls].
928 static bool isInstanceOf( 917 static bool isInstanceOf(
929 TypeMask typeMask, 918 TypeMask typeMask, ClassElement cls, ClassWorld classWorld) {
930 ClassElement cls, 919 return classWorld.isImplemented(cls) && typeMask.satisfies(cls, classWorld);
931 ClassWorld classWorld) {
932 return classWorld.isImplemented(cls) &&
933 typeMask.satisfies(cls, classWorld);
934 } 920 }
935 921
936 bool canBePrimitive(Compiler compiler) { 922 bool canBePrimitive(Compiler compiler) {
937 return canBePrimitiveNumber(compiler) 923 return canBePrimitiveNumber(compiler) ||
938 || canBePrimitiveArray(compiler) 924 canBePrimitiveArray(compiler) ||
939 || canBePrimitiveBoolean(compiler) 925 canBePrimitiveBoolean(compiler) ||
940 || canBePrimitiveString(compiler) 926 canBePrimitiveString(compiler) ||
941 || isNull(); 927 isNull();
942 } 928 }
943 929
944 bool canBePrimitiveNumber(Compiler compiler) { 930 bool canBePrimitiveNumber(Compiler compiler) {
945 ClassWorld classWorld = compiler.world; 931 ClassWorld classWorld = compiler.world;
946 JavaScriptBackend backend = compiler.backend; 932 JavaScriptBackend backend = compiler.backend;
947 BackendHelpers helpers = backend.helpers; 933 BackendHelpers helpers = backend.helpers;
948 // TODO(sra): It should be possible to test only jsDoubleClass and 934 // TODO(sra): It should be possible to test only jsDoubleClass and
949 // jsUInt31Class, since all others are superclasses of these two. 935 // jsUInt31Class, since all others are superclasses of these two.
950 return containsType(instructionType, helpers.jsNumberClass, classWorld) 936 return containsType(instructionType, helpers.jsNumberClass, classWorld) ||
951 || containsType(instructionType, helpers.jsIntClass, classWorld) 937 containsType(instructionType, helpers.jsIntClass, classWorld) ||
952 || containsType(instructionType, helpers.jsPositiveIntClass, classWorld) 938 containsType(instructionType, helpers.jsPositiveIntClass, classWorld) ||
953 || containsType(instructionType, helpers.jsUInt32Class, classWorld) 939 containsType(instructionType, helpers.jsUInt32Class, classWorld) ||
954 || containsType(instructionType, helpers.jsUInt31Class, classWorld) 940 containsType(instructionType, helpers.jsUInt31Class, classWorld) ||
955 || containsType(instructionType, helpers.jsDoubleClass, classWorld); 941 containsType(instructionType, helpers.jsDoubleClass, classWorld);
956 } 942 }
957 943
958 bool canBePrimitiveBoolean(Compiler compiler) { 944 bool canBePrimitiveBoolean(Compiler compiler) {
959 ClassWorld classWorld = compiler.world; 945 ClassWorld classWorld = compiler.world;
960 JavaScriptBackend backend = compiler.backend; 946 JavaScriptBackend backend = compiler.backend;
961 BackendHelpers helpers = backend.helpers; 947 BackendHelpers helpers = backend.helpers;
962 return containsType(instructionType, helpers.jsBoolClass, classWorld); 948 return containsType(instructionType, helpers.jsBoolClass, classWorld);
963 } 949 }
964 950
965 bool canBePrimitiveArray(Compiler compiler) { 951 bool canBePrimitiveArray(Compiler compiler) {
966 ClassWorld classWorld = compiler.world; 952 ClassWorld classWorld = compiler.world;
967 JavaScriptBackend backend = compiler.backend; 953 JavaScriptBackend backend = compiler.backend;
968 BackendHelpers helpers = backend.helpers; 954 BackendHelpers helpers = backend.helpers;
969 return containsType(instructionType, helpers.jsArrayClass, classWorld) 955 return containsType(instructionType, helpers.jsArrayClass, classWorld) ||
970 || containsType(instructionType, helpers.jsFixedArrayClass, classWorld) 956 containsType(instructionType, helpers.jsFixedArrayClass, classWorld) ||
971 || containsType( 957 containsType(
972 instructionType, helpers.jsExtendableArrayClass, classWorld) 958 instructionType, helpers.jsExtendableArrayClass, classWorld) ||
973 || containsType(instructionType, 959 containsType(
974 helpers.jsUnmodifiableArrayClass, classWorld); 960 instructionType, helpers.jsUnmodifiableArrayClass, classWorld);
975 } 961 }
976 962
977 bool isIndexablePrimitive(Compiler compiler) { 963 bool isIndexablePrimitive(Compiler compiler) {
978 ClassWorld classWorld = compiler.world; 964 ClassWorld classWorld = compiler.world;
979 JavaScriptBackend backend = compiler.backend; 965 JavaScriptBackend backend = compiler.backend;
980 BackendHelpers helpers = backend.helpers; 966 BackendHelpers helpers = backend.helpers;
981 return instructionType.containsOnlyString(classWorld) 967 return instructionType.containsOnlyString(classWorld) ||
982 || isInstanceOf(instructionType, helpers.jsIndexableClass, classWorld); 968 isInstanceOf(instructionType, helpers.jsIndexableClass, classWorld);
983 } 969 }
984 970
985 bool isFixedArray(Compiler compiler) { 971 bool isFixedArray(Compiler compiler) {
986 ClassWorld classWorld = compiler.world; 972 ClassWorld classWorld = compiler.world;
987 JavaScriptBackend backend = compiler.backend; 973 JavaScriptBackend backend = compiler.backend;
988 BackendHelpers helpers = backend.helpers; 974 BackendHelpers helpers = backend.helpers;
989 // TODO(sra): Recognize the union of these types as well. 975 // TODO(sra): Recognize the union of these types as well.
990 return containsOnlyType( 976 return containsOnlyType(
991 instructionType, helpers.jsFixedArrayClass, classWorld) 977 instructionType, helpers.jsFixedArrayClass, classWorld) ||
992 || containsOnlyType( 978 containsOnlyType(
993 instructionType, helpers.jsUnmodifiableArrayClass, classWorld); 979 instructionType, helpers.jsUnmodifiableArrayClass, classWorld);
994 } 980 }
995 981
996 bool isExtendableArray(Compiler compiler) { 982 bool isExtendableArray(Compiler compiler) {
997 ClassWorld classWorld = compiler.world; 983 ClassWorld classWorld = compiler.world;
998 JavaScriptBackend backend = compiler.backend; 984 JavaScriptBackend backend = compiler.backend;
999 BackendHelpers helpers = backend.helpers; 985 BackendHelpers helpers = backend.helpers;
1000 return containsOnlyType( 986 return containsOnlyType(
1001 instructionType, helpers.jsExtendableArrayClass, classWorld); 987 instructionType, helpers.jsExtendableArrayClass, classWorld);
1002 } 988 }
(...skipping 10 matching lines...) Expand all
1013 ClassWorld classWorld = compiler.world; 999 ClassWorld classWorld = compiler.world;
1014 JavaScriptBackend backend = compiler.backend; 1000 JavaScriptBackend backend = compiler.backend;
1015 BackendHelpers helpers = backend.helpers; 1001 BackendHelpers helpers = backend.helpers;
1016 return isInstanceOf(instructionType, helpers.jsArrayClass, classWorld); 1002 return isInstanceOf(instructionType, helpers.jsArrayClass, classWorld);
1017 } 1003 }
1018 1004
1019 bool isMutableIndexable(Compiler compiler) { 1005 bool isMutableIndexable(Compiler compiler) {
1020 ClassWorld classWorld = compiler.world; 1006 ClassWorld classWorld = compiler.world;
1021 JavaScriptBackend backend = compiler.backend; 1007 JavaScriptBackend backend = compiler.backend;
1022 BackendHelpers helpers = backend.helpers; 1008 BackendHelpers helpers = backend.helpers;
1023 return isInstanceOf(instructionType, 1009 return isInstanceOf(
1024 helpers.jsMutableIndexableClass, classWorld); 1010 instructionType, helpers.jsMutableIndexableClass, classWorld);
1025 } 1011 }
1026 1012
1027 bool isArray(Compiler compiler) => isReadableArray(compiler); 1013 bool isArray(Compiler compiler) => isReadableArray(compiler);
1028 1014
1029 bool canBePrimitiveString(Compiler compiler) { 1015 bool canBePrimitiveString(Compiler compiler) {
1030 ClassWorld classWorld = compiler.world; 1016 ClassWorld classWorld = compiler.world;
1031 JavaScriptBackend backend = compiler.backend; 1017 JavaScriptBackend backend = compiler.backend;
1032 BackendHelpers helpers = backend.helpers; 1018 BackendHelpers helpers = backend.helpers;
1033 return containsType(instructionType, helpers.jsStringClass, classWorld); 1019 return containsType(instructionType, helpers.jsStringClass, classWorld);
1034 } 1020 }
1035 1021
1036 bool isInteger(Compiler compiler) { 1022 bool isInteger(Compiler compiler) {
1037 ClassWorld classWorld = compiler.world; 1023 ClassWorld classWorld = compiler.world;
1038 return instructionType.containsOnlyInt(classWorld) 1024 return instructionType.containsOnlyInt(classWorld) &&
1039 && !instructionType.isNullable; 1025 !instructionType.isNullable;
1040 } 1026 }
1041 1027
1042 bool isUInt32(Compiler compiler) { 1028 bool isUInt32(Compiler compiler) {
1043 ClassWorld classWorld = compiler.world; 1029 ClassWorld classWorld = compiler.world;
1044 JavaScriptBackend backend = compiler.backend; 1030 JavaScriptBackend backend = compiler.backend;
1045 BackendHelpers helpers = backend.helpers; 1031 BackendHelpers helpers = backend.helpers;
1046 return !instructionType.isNullable 1032 return !instructionType.isNullable &&
1047 && isInstanceOf(instructionType, helpers.jsUInt32Class, classWorld); 1033 isInstanceOf(instructionType, helpers.jsUInt32Class, classWorld);
1048 } 1034 }
1049 1035
1050 bool isUInt31(Compiler compiler) { 1036 bool isUInt31(Compiler compiler) {
1051 ClassWorld classWorld = compiler.world; 1037 ClassWorld classWorld = compiler.world;
1052 JavaScriptBackend backend = compiler.backend; 1038 JavaScriptBackend backend = compiler.backend;
1053 BackendHelpers helpers = backend.helpers; 1039 BackendHelpers helpers = backend.helpers;
1054 return !instructionType.isNullable 1040 return !instructionType.isNullable &&
1055 && isInstanceOf(instructionType, helpers.jsUInt31Class, classWorld); 1041 isInstanceOf(instructionType, helpers.jsUInt31Class, classWorld);
1056 } 1042 }
1057 1043
1058 bool isPositiveInteger(Compiler compiler) { 1044 bool isPositiveInteger(Compiler compiler) {
1059 ClassWorld classWorld = compiler.world; 1045 ClassWorld classWorld = compiler.world;
1060 JavaScriptBackend backend = compiler.backend; 1046 JavaScriptBackend backend = compiler.backend;
1061 BackendHelpers helpers = backend.helpers; 1047 BackendHelpers helpers = backend.helpers;
1062 return !instructionType.isNullable && 1048 return !instructionType.isNullable &&
1063 isInstanceOf(instructionType, helpers.jsPositiveIntClass, classWorld); 1049 isInstanceOf(instructionType, helpers.jsPositiveIntClass, classWorld);
1064 } 1050 }
1065 1051
1066 bool isPositiveIntegerOrNull(Compiler compiler) { 1052 bool isPositiveIntegerOrNull(Compiler compiler) {
1067 ClassWorld classWorld = compiler.world; 1053 ClassWorld classWorld = compiler.world;
1068 JavaScriptBackend backend = compiler.backend; 1054 JavaScriptBackend backend = compiler.backend;
1069 BackendHelpers helpers = backend.helpers; 1055 BackendHelpers helpers = backend.helpers;
1070 return isInstanceOf( 1056 return isInstanceOf(
1071 instructionType, helpers.jsPositiveIntClass, classWorld); 1057 instructionType, helpers.jsPositiveIntClass, classWorld);
1072 } 1058 }
1073 1059
1074 bool isIntegerOrNull(Compiler compiler) { 1060 bool isIntegerOrNull(Compiler compiler) {
1075 ClassWorld classWorld = compiler.world; 1061 ClassWorld classWorld = compiler.world;
1076 return instructionType.containsOnlyInt(classWorld); 1062 return instructionType.containsOnlyInt(classWorld);
1077 } 1063 }
1078 1064
1079 bool isNumber(Compiler compiler) { 1065 bool isNumber(Compiler compiler) {
1080 ClassWorld classWorld = compiler.world; 1066 ClassWorld classWorld = compiler.world;
1081 return instructionType.containsOnlyNum(classWorld) 1067 return instructionType.containsOnlyNum(classWorld) &&
1082 && !instructionType.isNullable; 1068 !instructionType.isNullable;
1083 } 1069 }
1084 1070
1085 bool isNumberOrNull(Compiler compiler) { 1071 bool isNumberOrNull(Compiler compiler) {
1086 ClassWorld classWorld = compiler.world; 1072 ClassWorld classWorld = compiler.world;
1087 return instructionType.containsOnlyNum(classWorld); 1073 return instructionType.containsOnlyNum(classWorld);
1088 } 1074 }
1089 1075
1090 bool isDouble(Compiler compiler) { 1076 bool isDouble(Compiler compiler) {
1091 ClassWorld classWorld = compiler.world; 1077 ClassWorld classWorld = compiler.world;
1092 return instructionType.containsOnlyDouble(classWorld) 1078 return instructionType.containsOnlyDouble(classWorld) &&
1093 && !instructionType.isNullable; 1079 !instructionType.isNullable;
1094 } 1080 }
1095 1081
1096 bool isDoubleOrNull(Compiler compiler) { 1082 bool isDoubleOrNull(Compiler compiler) {
1097 ClassWorld classWorld = compiler.world; 1083 ClassWorld classWorld = compiler.world;
1098 return instructionType.containsOnlyDouble(classWorld); 1084 return instructionType.containsOnlyDouble(classWorld);
1099 } 1085 }
1100 1086
1101 bool isBoolean(Compiler compiler) { 1087 bool isBoolean(Compiler compiler) {
1102 ClassWorld classWorld = compiler.world; 1088 ClassWorld classWorld = compiler.world;
1103 return instructionType.containsOnlyBool(classWorld) 1089 return instructionType.containsOnlyBool(classWorld) &&
1104 && !instructionType.isNullable; 1090 !instructionType.isNullable;
1105 } 1091 }
1106 1092
1107 bool isBooleanOrNull(Compiler compiler) { 1093 bool isBooleanOrNull(Compiler compiler) {
1108 ClassWorld classWorld = compiler.world; 1094 ClassWorld classWorld = compiler.world;
1109 return instructionType.containsOnlyBool(classWorld); 1095 return instructionType.containsOnlyBool(classWorld);
1110 } 1096 }
1111 1097
1112 bool isString(Compiler compiler) { 1098 bool isString(Compiler compiler) {
1113 ClassWorld classWorld = compiler.world; 1099 ClassWorld classWorld = compiler.world;
1114 return instructionType.containsOnlyString(classWorld) 1100 return instructionType.containsOnlyString(classWorld) &&
1115 && !instructionType.isNullable; 1101 !instructionType.isNullable;
1116 } 1102 }
1117 1103
1118 bool isStringOrNull(Compiler compiler) { 1104 bool isStringOrNull(Compiler compiler) {
1119 ClassWorld classWorld = compiler.world; 1105 ClassWorld classWorld = compiler.world;
1120 return instructionType.containsOnlyString(classWorld); 1106 return instructionType.containsOnlyString(classWorld);
1121 } 1107 }
1122 1108
1123 bool isPrimitive(Compiler compiler) { 1109 bool isPrimitive(Compiler compiler) {
1124 return (isPrimitiveOrNull(compiler) && !instructionType.isNullable) 1110 return (isPrimitiveOrNull(compiler) && !instructionType.isNullable) ||
1125 || isNull(); 1111 isNull();
1126 } 1112 }
1127 1113
1128 bool isPrimitiveOrNull(Compiler compiler) { 1114 bool isPrimitiveOrNull(Compiler compiler) {
1129 return isIndexablePrimitive(compiler) 1115 return isIndexablePrimitive(compiler) ||
1130 || isNumberOrNull(compiler) 1116 isNumberOrNull(compiler) ||
1131 || isBooleanOrNull(compiler) 1117 isBooleanOrNull(compiler) ||
1132 || isNull(); 1118 isNull();
1133 } 1119 }
1134 1120
1135 /** 1121 /**
1136 * Type of the instruction. 1122 * Type of the instruction.
1137 */ 1123 */
1138 TypeMask instructionType; 1124 TypeMask instructionType;
1139 1125
1140 Selector get selector => null; 1126 Selector get selector => null;
1141 HInstruction getDartReceiver(Compiler compiler) => null; 1127 HInstruction getDartReceiver(Compiler compiler) => null;
1142 bool onlyThrowsNSM() => false; 1128 bool onlyThrowsNSM() => false;
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 users.remove(current); 1271 users.remove(current);
1286 if (--usersInCurrentBlock == 0) break; 1272 if (--usersInCurrentBlock == 0) break;
1287 } 1273 }
1288 current = current.next; 1274 current = current.next;
1289 } 1275 }
1290 } 1276 }
1291 1277
1292 return users; 1278 return users;
1293 } 1279 }
1294 1280
1295 void replaceAllUsersDominatedBy(HInstruction cursor, 1281 void replaceAllUsersDominatedBy(
1296 HInstruction newInstruction) { 1282 HInstruction cursor, HInstruction newInstruction) {
1297 Setlet<HInstruction> users = dominatedUsers(cursor); 1283 Setlet<HInstruction> users = dominatedUsers(cursor);
1298 for (HInstruction user in users) { 1284 for (HInstruction user in users) {
1299 user.changeUse(this, newInstruction); 1285 user.changeUse(this, newInstruction);
1300 } 1286 }
1301 } 1287 }
1302 1288
1303 void moveBefore(HInstruction other) { 1289 void moveBefore(HInstruction other) {
1304 assert(this is !HControlFlow); 1290 assert(this is! HControlFlow);
1305 assert(this is !HPhi); 1291 assert(this is! HPhi);
1306 assert(other is !HPhi); 1292 assert(other is! HPhi);
1307 block.detach(this); 1293 block.detach(this);
1308 other.block.internalAddBefore(other, this); 1294 other.block.internalAddBefore(other, this);
1309 block = other.block; 1295 block = other.block;
1310 } 1296 }
1311 1297
1312 bool isConstant() => false; 1298 bool isConstant() => false;
1313 bool isConstantBoolean() => false; 1299 bool isConstantBoolean() => false;
1314 bool isConstantNull() => false; 1300 bool isConstantNull() => false;
1315 bool isConstantNumber() => false; 1301 bool isConstantNumber() => false;
1316 bool isConstantInteger() => false; 1302 bool isConstantInteger() => false;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 Element element = type.element; 1346 Element element = type.element;
1361 JavaScriptBackend backend = compiler.backend; 1347 JavaScriptBackend backend = compiler.backend;
1362 if (type.kind != TypeKind.INTERFACE) { 1348 if (type.kind != TypeKind.INTERFACE) {
1363 return new HTypeConversion(type, kind, backend.dynamicType, this); 1349 return new HTypeConversion(type, kind, backend.dynamicType, this);
1364 } else if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) { 1350 } else if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) {
1365 // Boolean conversion checks work on non-nullable booleans. 1351 // Boolean conversion checks work on non-nullable booleans.
1366 return new HTypeConversion(type, kind, backend.boolType, this); 1352 return new HTypeConversion(type, kind, backend.boolType, this);
1367 } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) { 1353 } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) {
1368 throw 'creating compound check to $type (this = ${this})'; 1354 throw 'creating compound check to $type (this = ${this})';
1369 } else { 1355 } else {
1370 TypeMask subtype = new TypeMask.subtype(element.declaration, 1356 TypeMask subtype =
1371 compiler.world); 1357 new TypeMask.subtype(element.declaration, compiler.world);
1372 return new HTypeConversion(type, kind, subtype, this); 1358 return new HTypeConversion(type, kind, subtype, this);
1373 } 1359 }
1374 } 1360 }
1375 1361
1376 /** 1362 /**
1377 * Return whether the instructions do not belong to a loop or 1363 * Return whether the instructions do not belong to a loop or
1378 * belong to the same loop. 1364 * belong to the same loop.
1379 */ 1365 */
1380 bool hasSameLoopHeaderAs(HInstruction other) { 1366 bool hasSameLoopHeaderAs(HInstruction other) {
1381 return block.enclosingLoopHeader == other.block.enclosingLoopHeader; 1367 return block.enclosingLoopHeader == other.block.enclosingLoopHeader;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1503 static const int ARGUMENTS_OFFSET = 1; 1489 static const int ARGUMENTS_OFFSET = 1;
1504 bool canThrow() => true; 1490 bool canThrow() => true;
1505 1491
1506 /** 1492 /**
1507 * Returns whether this call is on an intercepted method. 1493 * Returns whether this call is on an intercepted method.
1508 */ 1494 */
1509 bool get isInterceptedCall { 1495 bool get isInterceptedCall {
1510 // We know it's a selector call if it follows the interceptor 1496 // We know it's a selector call if it follows the interceptor
1511 // calling convention, which adds the actual receiver as a 1497 // calling convention, which adds the actual receiver as a
1512 // parameter to the call. 1498 // parameter to the call.
1513 return (selector != null) && 1499 return (selector != null) && (inputs.length - 2 == selector.argumentCount);
1514 (inputs.length - 2 == selector.argumentCount);
1515 } 1500 }
1516 } 1501 }
1517 1502
1518 abstract class HInvokeDynamic extends HInvoke { 1503 abstract class HInvokeDynamic extends HInvoke {
1519 final InvokeDynamicSpecializer specializer; 1504 final InvokeDynamicSpecializer specializer;
1520 Selector selector; 1505 Selector selector;
1521 TypeMask mask; 1506 TypeMask mask;
1522 Element element; 1507 Element element;
1523 1508
1524 HInvokeDynamic(Selector selector, 1509 HInvokeDynamic(Selector selector, this.mask, this.element,
1525 this.mask, 1510 List<HInstruction> inputs, TypeMask type,
1526 this.element, 1511 [bool isIntercepted = false])
1527 List<HInstruction> inputs, 1512 : super(inputs, type),
1528 TypeMask type, 1513 this.selector = selector,
1529 [bool isIntercepted = false]) 1514 specializer = isIntercepted
1530 : super(inputs, type), 1515 ? InvokeDynamicSpecializer.lookupSpecializer(selector)
1531 this.selector = selector, 1516 : const InvokeDynamicSpecializer();
1532 specializer = isIntercepted
1533 ? InvokeDynamicSpecializer.lookupSpecializer(selector)
1534 : const InvokeDynamicSpecializer();
1535 toString() => 'invoke dynamic: selector=$selector, mask=$mask'; 1517 toString() => 'invoke dynamic: selector=$selector, mask=$mask';
1536 HInstruction get receiver => inputs[0]; 1518 HInstruction get receiver => inputs[0];
1537 HInstruction getDartReceiver(Compiler compiler) { 1519 HInstruction getDartReceiver(Compiler compiler) {
1538 return isCallOnInterceptor(compiler) ? inputs[1] : inputs[0]; 1520 return isCallOnInterceptor(compiler) ? inputs[1] : inputs[0];
1539 } 1521 }
1540 1522
1541 /** 1523 /**
1542 * Returns whether this call is on an interceptor object. 1524 * Returns whether this call is on an interceptor object.
1543 */ 1525 */
1544 bool isCallOnInterceptor(Compiler compiler) { 1526 bool isCallOnInterceptor(Compiler compiler) {
1545 return isInterceptedCall && receiver.isInterceptor(compiler); 1527 return isInterceptedCall && receiver.isInterceptor(compiler);
1546 } 1528 }
1547 1529
1548 int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE; 1530 int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
1549 bool typeEquals(other) => other is HInvokeDynamic; 1531 bool typeEquals(other) => other is HInvokeDynamic;
1550 bool dataEquals(HInvokeDynamic other) { 1532 bool dataEquals(HInvokeDynamic other) {
1551 // Use the name and the kind instead of [Selector.operator==] 1533 // Use the name and the kind instead of [Selector.operator==]
1552 // because we don't need to check the arity (already checked in 1534 // because we don't need to check the arity (already checked in
1553 // [gvnEquals]), and the receiver types may not be in sync. 1535 // [gvnEquals]), and the receiver types may not be in sync.
1554 return selector.name == other.selector.name 1536 return selector.name == other.selector.name &&
1555 && selector.kind == other.selector.kind; 1537 selector.kind == other.selector.kind;
1556 } 1538 }
1557 } 1539 }
1558 1540
1559 class HInvokeClosure extends HInvokeDynamic { 1541 class HInvokeClosure extends HInvokeDynamic {
1560 HInvokeClosure(Selector selector, 1542 HInvokeClosure(Selector selector, List<HInstruction> inputs, TypeMask type)
1561 List<HInstruction> inputs,
1562 TypeMask type)
1563 : super(selector, null, null, inputs, type) { 1543 : super(selector, null, null, inputs, type) {
1564 assert(selector.isClosureCall); 1544 assert(selector.isClosureCall);
1565 } 1545 }
1566 accept(HVisitor visitor) => visitor.visitInvokeClosure(this); 1546 accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
1567 } 1547 }
1568 1548
1569 class HInvokeDynamicMethod extends HInvokeDynamic { 1549 class HInvokeDynamicMethod extends HInvokeDynamic {
1570 HInvokeDynamicMethod(Selector selector, 1550 HInvokeDynamicMethod(Selector selector, TypeMask mask,
1571 TypeMask mask, 1551 List<HInstruction> inputs, TypeMask type,
1572 List<HInstruction> inputs, 1552 [bool isIntercepted = false])
1573 TypeMask type, 1553 : super(selector, mask, null, inputs, type, isIntercepted);
1574 [bool isIntercepted = false])
1575 : super(selector, mask, null, inputs, type, isIntercepted);
1576 1554
1577 String toString() => 'invoke dynamic method: selector=$selector, mask=$mask'; 1555 String toString() => 'invoke dynamic method: selector=$selector, mask=$mask';
1578 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this); 1556 accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
1579 } 1557 }
1580 1558
1581 abstract class HInvokeDynamicField extends HInvokeDynamic { 1559 abstract class HInvokeDynamicField extends HInvokeDynamic {
1582 HInvokeDynamicField( 1560 HInvokeDynamicField(Selector selector, TypeMask mask, Element element,
1583 Selector selector, TypeMask mask, 1561 List<HInstruction> inputs, TypeMask type)
1584 Element element, List<HInstruction> inputs,
1585 TypeMask type)
1586 : super(selector, mask, element, inputs, type); 1562 : super(selector, mask, element, inputs, type);
1587 toString() => 'invoke dynamic field: selector=$selector, mask=$mask'; 1563 toString() => 'invoke dynamic field: selector=$selector, mask=$mask';
1588 } 1564 }
1589 1565
1590 class HInvokeDynamicGetter extends HInvokeDynamicField { 1566 class HInvokeDynamicGetter extends HInvokeDynamicField {
1591 HInvokeDynamicGetter(Selector selector, TypeMask mask, 1567 HInvokeDynamicGetter(Selector selector, TypeMask mask, Element element,
1592 Element element, List<HInstruction> inputs, TypeMask type) 1568 List<HInstruction> inputs, TypeMask type)
1593 : super(selector, mask, element, inputs, type); 1569 : super(selector, mask, element, inputs, type);
1594 toString() => 'invoke dynamic getter: selector=$selector, mask=$mask'; 1570 toString() => 'invoke dynamic getter: selector=$selector, mask=$mask';
1595 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this); 1571 accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
1596 } 1572 }
1597 1573
1598 class HInvokeDynamicSetter extends HInvokeDynamicField { 1574 class HInvokeDynamicSetter extends HInvokeDynamicField {
1599 HInvokeDynamicSetter(Selector selector, TypeMask mask, 1575 HInvokeDynamicSetter(Selector selector, TypeMask mask, Element element,
1600 Element element, List<HInstruction> inputs, TypeMask type) 1576 List<HInstruction> inputs, TypeMask type)
1601 : super(selector, mask, element, inputs, type); 1577 : super(selector, mask, element, inputs, type);
1602 toString() => 'invoke dynamic setter: selector=$selector, mask=$mask'; 1578 toString() => 'invoke dynamic setter: selector=$selector, mask=$mask';
1603 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this); 1579 accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
1604 } 1580 }
1605 1581
1606 class HInvokeStatic extends HInvoke { 1582 class HInvokeStatic extends HInvoke {
1607 final Element element; 1583 final Element element;
1608 1584
1609 final bool targetCanThrow; 1585 final bool targetCanThrow;
1610 1586
1611 bool canThrow() => targetCanThrow; 1587 bool canThrow() => targetCanThrow;
1612 1588
1613 /// If this instruction is a call to a constructor, [instantiatedTypes] 1589 /// If this instruction is a call to a constructor, [instantiatedTypes]
1614 /// contains the type(s) used in the (Dart) `New` expression(s). The 1590 /// contains the type(s) used in the (Dart) `New` expression(s). The
1615 /// [instructionType] of this node is not enough, because we also need the 1591 /// [instructionType] of this node is not enough, because we also need the
1616 /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations]. 1592 /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
1617 List<DartType> instantiatedTypes; 1593 List<DartType> instantiatedTypes;
1618 1594
1619 /** The first input must be the target. */ 1595 /** The first input must be the target. */
1620 HInvokeStatic(this.element, inputs, TypeMask type, 1596 HInvokeStatic(this.element, inputs, TypeMask type,
1621 {this.targetCanThrow: true}) 1597 {this.targetCanThrow: true})
1622 : super(inputs, type); 1598 : super(inputs, type);
1623 1599
1624 toString() => 'invoke static: $element'; 1600 toString() => 'invoke static: $element';
1625 accept(HVisitor visitor) => visitor.visitInvokeStatic(this); 1601 accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
1626 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE; 1602 int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE;
1627 } 1603 }
1628 1604
1629 class HInvokeSuper extends HInvokeStatic { 1605 class HInvokeSuper extends HInvokeStatic {
1630 /** The class where the call to super is being done. */ 1606 /** The class where the call to super is being done. */
1631 final ClassElement caller; 1607 final ClassElement caller;
1632 final bool isSetter; 1608 final bool isSetter;
1633 final Selector selector; 1609 final Selector selector;
1634 1610
1635 HInvokeSuper(Element element, 1611 HInvokeSuper(Element element, this.caller, this.selector, inputs, type,
1636 this.caller, 1612 SourceInformation sourceInformation,
1637 this.selector, 1613 {this.isSetter})
1638 inputs,
1639 type,
1640 SourceInformation sourceInformation,
1641 {this.isSetter})
1642 : super(element, inputs, type) { 1614 : super(element, inputs, type) {
1643 this.sourceInformation = sourceInformation; 1615 this.sourceInformation = sourceInformation;
1644 } 1616 }
1645 1617
1646 HInstruction get receiver => inputs[0]; 1618 HInstruction get receiver => inputs[0];
1647 HInstruction getDartReceiver(Compiler compiler) { 1619 HInstruction getDartReceiver(Compiler compiler) {
1648 return isCallOnInterceptor(compiler) ? inputs[1] : inputs[0]; 1620 return isCallOnInterceptor(compiler) ? inputs[1] : inputs[0];
1649 } 1621 }
1650 1622
1651 /** 1623 /**
(...skipping 10 matching lines...) Expand all
1662 assert(isSetter); 1634 assert(isSetter);
1663 // The 'inputs' are [receiver, value] or [interceptor, receiver, value]. 1635 // The 'inputs' are [receiver, value] or [interceptor, receiver, value].
1664 return inputs.last; 1636 return inputs.last;
1665 } 1637 }
1666 } 1638 }
1667 1639
1668 class HInvokeConstructorBody extends HInvokeStatic { 1640 class HInvokeConstructorBody extends HInvokeStatic {
1669 // The 'inputs' are 1641 // The 'inputs' are
1670 // [receiver, arg1, ..., argN] or 1642 // [receiver, arg1, ..., argN] or
1671 // [interceptor, receiver, arg1, ... argN]. 1643 // [interceptor, receiver, arg1, ... argN].
1672 HInvokeConstructorBody(element, inputs, type) 1644 HInvokeConstructorBody(element, inputs, type) : super(element, inputs, type);
1673 : super(element, inputs, type);
1674 1645
1675 String toString() => 'invoke constructor body: ${element.name}'; 1646 String toString() => 'invoke constructor body: ${element.name}';
1676 accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this); 1647 accept(HVisitor visitor) => visitor.visitInvokeConstructorBody(this);
1677 } 1648 }
1678 1649
1679 abstract class HFieldAccess extends HInstruction { 1650 abstract class HFieldAccess extends HInstruction {
1680 final Element element; 1651 final Element element;
1681 1652
1682 HFieldAccess(Element element, List<HInstruction> inputs, TypeMask type) 1653 HFieldAccess(Element element, List<HInstruction> inputs, TypeMask type)
1683 : this.element = element, super(inputs, type); 1654 : this.element = element,
1655 super(inputs, type);
1684 1656
1685 HInstruction get receiver => inputs[0]; 1657 HInstruction get receiver => inputs[0];
1686 } 1658 }
1687 1659
1688 class HFieldGet extends HFieldAccess { 1660 class HFieldGet extends HFieldAccess {
1689 final bool isAssignable; 1661 final bool isAssignable;
1690 1662
1691 HFieldGet(Element element, 1663 HFieldGet(Element element, HInstruction receiver, TypeMask type,
1692 HInstruction receiver, 1664 {bool isAssignable})
1693 TypeMask type, 1665 : this.isAssignable =
1694 {bool isAssignable}) 1666 (isAssignable != null) ? isAssignable : element.isAssignable,
1695 : this.isAssignable = (isAssignable != null)
1696 ? isAssignable
1697 : element.isAssignable,
1698 super(element, <HInstruction>[receiver], type) { 1667 super(element, <HInstruction>[receiver], type) {
1699 sideEffects.clearAllSideEffects(); 1668 sideEffects.clearAllSideEffects();
1700 sideEffects.clearAllDependencies(); 1669 sideEffects.clearAllDependencies();
1701 setUseGvn(); 1670 setUseGvn();
1702 if (this.isAssignable) { 1671 if (this.isAssignable) {
1703 sideEffects.setDependsOnInstancePropertyStore(); 1672 sideEffects.setDependsOnInstancePropertyStore();
1704 } 1673 }
1705 } 1674 }
1706 1675
1707 bool isInterceptor(Compiler compiler) { 1676 bool isInterceptor(Compiler compiler) {
(...skipping 17 matching lines...) Expand all
1725 1694
1726 accept(HVisitor visitor) => visitor.visitFieldGet(this); 1695 accept(HVisitor visitor) => visitor.visitFieldGet(this);
1727 1696
1728 int typeCode() => HInstruction.FIELD_GET_TYPECODE; 1697 int typeCode() => HInstruction.FIELD_GET_TYPECODE;
1729 bool typeEquals(other) => other is HFieldGet; 1698 bool typeEquals(other) => other is HFieldGet;
1730 bool dataEquals(HFieldGet other) => element == other.element; 1699 bool dataEquals(HFieldGet other) => element == other.element;
1731 String toString() => "FieldGet $element"; 1700 String toString() => "FieldGet $element";
1732 } 1701 }
1733 1702
1734 class HFieldSet extends HFieldAccess { 1703 class HFieldSet extends HFieldAccess {
1735 HFieldSet(Element element, 1704 HFieldSet(Element element, HInstruction receiver, HInstruction value)
1736 HInstruction receiver,
1737 HInstruction value)
1738 : super(element, <HInstruction>[receiver, value], 1705 : super(element, <HInstruction>[receiver, value],
1739 const TypeMask.nonNullEmpty()) { 1706 const TypeMask.nonNullEmpty()) {
1740 sideEffects.clearAllSideEffects(); 1707 sideEffects.clearAllSideEffects();
1741 sideEffects.clearAllDependencies(); 1708 sideEffects.clearAllDependencies();
1742 sideEffects.setChangesInstanceProperty(); 1709 sideEffects.setChangesInstanceProperty();
1743 } 1710 }
1744 1711
1745 bool canThrow() => receiver.canBeNull(); 1712 bool canThrow() => receiver.canBeNull();
1746 1713
1747 HInstruction getDartReceiver(Compiler compiler) => receiver; 1714 HInstruction getDartReceiver(Compiler compiler) => receiver;
1748 bool onlyThrowsNSM() => true; 1715 bool onlyThrowsNSM() => true;
1749 1716
1750 HInstruction get value => inputs[1]; 1717 HInstruction get value => inputs[1];
1751 accept(HVisitor visitor) => visitor.visitFieldSet(this); 1718 accept(HVisitor visitor) => visitor.visitFieldSet(this);
1752 1719
1753 bool isJsStatement() => true; 1720 bool isJsStatement() => true;
1754 String toString() => "FieldSet $element"; 1721 String toString() => "FieldSet $element";
1755 } 1722 }
1756 1723
1757 /** 1724 /**
1758 * HReadModifyWrite is a late stage instruction for a field (property) update 1725 * HReadModifyWrite is a late stage instruction for a field (property) update
1759 * via an assignment operation or pre- or post-increment. 1726 * via an assignment operation or pre- or post-increment.
1760 */ 1727 */
1761 class HReadModifyWrite extends HLateInstruction { 1728 class HReadModifyWrite extends HLateInstruction {
1762 static const ASSIGN_OP = 0; 1729 static const ASSIGN_OP = 0;
1763 static const PRE_OP = 1; 1730 static const PRE_OP = 1;
1764 static const POST_OP = 2; 1731 static const POST_OP = 2;
1765 final Element element; 1732 final Element element;
1766 final String jsOp; 1733 final String jsOp;
1767 final int opKind; 1734 final int opKind;
1768 1735
1769 HReadModifyWrite._(Element this.element, this.jsOp, this.opKind, 1736 HReadModifyWrite._(Element this.element, this.jsOp, this.opKind,
1770 List<HInstruction> inputs, TypeMask type) 1737 List<HInstruction> inputs, TypeMask type)
1771 : super(inputs, type) { 1738 : super(inputs, type) {
1772 sideEffects.clearAllSideEffects(); 1739 sideEffects.clearAllSideEffects();
1773 sideEffects.clearAllDependencies(); 1740 sideEffects.clearAllDependencies();
1774 sideEffects.setChangesInstanceProperty(); 1741 sideEffects.setChangesInstanceProperty();
1775 sideEffects.setDependsOnInstancePropertyStore(); 1742 sideEffects.setDependsOnInstancePropertyStore();
1776 } 1743 }
1777 1744
1778 HReadModifyWrite.assignOp(Element element, String jsOp, 1745 HReadModifyWrite.assignOp(Element element, String jsOp, HInstruction receiver,
1779 HInstruction receiver, HInstruction operand, TypeMask type) 1746 HInstruction operand, TypeMask type)
1780 : this._(element, jsOp, ASSIGN_OP, 1747 : this._(
1781 <HInstruction>[receiver, operand], type); 1748 element, jsOp, ASSIGN_OP, <HInstruction>[receiver, operand], type);
1782 1749
1783 HReadModifyWrite.preOp(Element element, String jsOp, 1750 HReadModifyWrite.preOp(
1784 HInstruction receiver, TypeMask type) 1751 Element element, String jsOp, HInstruction receiver, TypeMask type)
1785 : this._(element, jsOp, PRE_OP, <HInstruction>[receiver], type); 1752 : this._(element, jsOp, PRE_OP, <HInstruction>[receiver], type);
1786 1753
1787 HReadModifyWrite.postOp(Element element, String jsOp, 1754 HReadModifyWrite.postOp(
1788 HInstruction receiver, TypeMask type) 1755 Element element, String jsOp, HInstruction receiver, TypeMask type)
1789 : this._(element, jsOp, POST_OP, <HInstruction>[receiver], type); 1756 : this._(element, jsOp, POST_OP, <HInstruction>[receiver], type);
1790 1757
1791 HInstruction get receiver => inputs[0]; 1758 HInstruction get receiver => inputs[0];
1792 1759
1793 bool get isPreOp => opKind == PRE_OP; 1760 bool get isPreOp => opKind == PRE_OP;
1794 bool get isPostOp => opKind == POST_OP; 1761 bool get isPostOp => opKind == POST_OP;
1795 bool get isAssignOp => opKind == ASSIGN_OP; 1762 bool get isAssignOp => opKind == ASSIGN_OP;
1796 1763
1797 bool canThrow() => receiver.canBeNull(); 1764 bool canThrow() => receiver.canBeNull();
1798 1765
(...skipping 13 matching lines...) Expand all
1812 HLocalAccess(this.variable, List<HInstruction> inputs, TypeMask type) 1779 HLocalAccess(this.variable, List<HInstruction> inputs, TypeMask type)
1813 : super(inputs, type); 1780 : super(inputs, type);
1814 1781
1815 HInstruction get receiver => inputs[0]; 1782 HInstruction get receiver => inputs[0];
1816 } 1783 }
1817 1784
1818 class HLocalGet extends HLocalAccess { 1785 class HLocalGet extends HLocalAccess {
1819 // No need to use GVN for a [HLocalGet], it is just a local 1786 // No need to use GVN for a [HLocalGet], it is just a local
1820 // access. 1787 // access.
1821 HLocalGet(Local variable, HLocalValue local, TypeMask type, 1788 HLocalGet(Local variable, HLocalValue local, TypeMask type,
1822 SourceInformation sourceInformation) 1789 SourceInformation sourceInformation)
1823 : super(variable, <HInstruction>[local], type) { 1790 : super(variable, <HInstruction>[local], type) {
1824 this.sourceInformation = sourceInformation; 1791 this.sourceInformation = sourceInformation;
1825 } 1792 }
1826 1793
1827 accept(HVisitor visitor) => visitor.visitLocalGet(this); 1794 accept(HVisitor visitor) => visitor.visitLocalGet(this);
1828 1795
1829 HLocalValue get local => inputs[0]; 1796 HLocalValue get local => inputs[0];
1830 } 1797 }
1831 1798
1832 class HLocalSet extends HLocalAccess { 1799 class HLocalSet extends HLocalAccess {
1833 HLocalSet(Local variable, HLocalValue local, HInstruction value) 1800 HLocalSet(Local variable, HLocalValue local, HInstruction value)
1834 : super(variable, <HInstruction>[local, value], 1801 : super(variable, <HInstruction>[local, value],
1835 const TypeMask.nonNullEmpty()); 1802 const TypeMask.nonNullEmpty());
1836 1803
1837 accept(HVisitor visitor) => visitor.visitLocalSet(this); 1804 accept(HVisitor visitor) => visitor.visitLocalSet(this);
1838 1805
1839 HLocalValue get local => inputs[0]; 1806 HLocalValue get local => inputs[0];
1840 HInstruction get value => inputs[1]; 1807 HInstruction get value => inputs[1];
1841 bool isJsStatement() => true; 1808 bool isJsStatement() => true;
1842 } 1809 }
1843 1810
1844 abstract class HForeign extends HInstruction { 1811 abstract class HForeign extends HInstruction {
1845 HForeign(TypeMask type, List<HInstruction> inputs) : super(inputs, type); 1812 HForeign(TypeMask type, List<HInstruction> inputs) : super(inputs, type);
1846 1813
1847 bool get isStatement => false; 1814 bool get isStatement => false;
1848 native.NativeBehavior get nativeBehavior => null; 1815 native.NativeBehavior get nativeBehavior => null;
1849 1816
1850 bool canThrow() { 1817 bool canThrow() {
1851 return sideEffects.hasSideEffects() 1818 return sideEffects.hasSideEffects() || sideEffects.dependsOnSomething();
1852 || sideEffects.dependsOnSomething();
1853 } 1819 }
1854 } 1820 }
1855 1821
1856 class HForeignCode extends HForeign { 1822 class HForeignCode extends HForeign {
1857 final js.Template codeTemplate; 1823 final js.Template codeTemplate;
1858 final bool isStatement; 1824 final bool isStatement;
1859 final native.NativeBehavior nativeBehavior; 1825 final native.NativeBehavior nativeBehavior;
1860 native.NativeThrowBehavior throwBehavior; 1826 native.NativeThrowBehavior throwBehavior;
1861 1827
1862 HForeignCode(this.codeTemplate, 1828 HForeignCode(this.codeTemplate, TypeMask type, List<HInstruction> inputs,
1863 TypeMask type,
1864 List<HInstruction> inputs,
1865 {this.isStatement: false, 1829 {this.isStatement: false,
1866 SideEffects effects, 1830 SideEffects effects,
1867 native.NativeBehavior nativeBehavior, 1831 native.NativeBehavior nativeBehavior,
1868 native.NativeThrowBehavior throwBehavior}) 1832 native.NativeThrowBehavior throwBehavior})
1869 : this.nativeBehavior = nativeBehavior, 1833 : this.nativeBehavior = nativeBehavior,
1870 this.throwBehavior = throwBehavior, 1834 this.throwBehavior = throwBehavior,
1871 super(type, inputs) { 1835 super(type, inputs) {
1872 assert(codeTemplate != null); 1836 assert(codeTemplate != null);
1873 if (effects == null && nativeBehavior != null) { 1837 if (effects == null && nativeBehavior != null) {
1874 effects = nativeBehavior.sideEffects; 1838 effects = nativeBehavior.sideEffects;
1875 } 1839 }
1876 if (this.throwBehavior == null) { 1840 if (this.throwBehavior == null) {
1877 this.throwBehavior = (nativeBehavior == null) 1841 this.throwBehavior = (nativeBehavior == null)
1878 ? native.NativeThrowBehavior.MAY 1842 ? native.NativeThrowBehavior.MAY
1879 : nativeBehavior.throwBehavior; 1843 : nativeBehavior.throwBehavior;
1880 } 1844 }
1881 assert(this.throwBehavior != null); 1845 assert(this.throwBehavior != null);
1882 1846
1883 if (effects != null) sideEffects.add(effects); 1847 if (effects != null) sideEffects.add(effects);
1884 } 1848 }
1885 1849
1886 HForeignCode.statement(js.Template codeTemplate, List<HInstruction> inputs, 1850 HForeignCode.statement(js.Template codeTemplate, List<HInstruction> inputs,
1887 SideEffects effects, 1851 SideEffects effects, native.NativeBehavior nativeBehavior, TypeMask type)
1888 native.NativeBehavior nativeBehavior, 1852 : this(codeTemplate, type, inputs,
1889 TypeMask type) 1853 isStatement: true,
1890 : this(codeTemplate, type, inputs, isStatement: true, 1854 effects: effects,
1891 effects: effects, nativeBehavior: nativeBehavior); 1855 nativeBehavior: nativeBehavior);
1892 1856
1893 accept(HVisitor visitor) => visitor.visitForeignCode(this); 1857 accept(HVisitor visitor) => visitor.visitForeignCode(this);
1894 1858
1895 bool isJsStatement() => isStatement; 1859 bool isJsStatement() => isStatement;
1896 bool canThrow() => canBeNull() 1860 bool canThrow() =>
1897 ? throwBehavior.canThrow 1861 canBeNull() ? throwBehavior.canThrow : throwBehavior.onNonNull.canThrow;
1898 : throwBehavior.onNonNull.canThrow;
1899 1862
1900 bool onlyThrowsNSM() => throwBehavior.isOnlyNullNSMGuard; 1863 bool onlyThrowsNSM() => throwBehavior.isOnlyNullNSMGuard;
1901 1864
1902 bool get isAllocation => nativeBehavior != null && 1865 bool get isAllocation =>
1903 nativeBehavior.isAllocation && 1866 nativeBehavior != null && nativeBehavior.isAllocation && !canBeNull();
1904 !canBeNull();
1905 1867
1906 String toString() => 'HForeignCode("${codeTemplate.source}",$inputs)'; 1868 String toString() => 'HForeignCode("${codeTemplate.source}",$inputs)';
1907 } 1869 }
1908 1870
1909 class HForeignNew extends HForeign { 1871 class HForeignNew extends HForeign {
1910 ClassElement element; 1872 ClassElement element;
1911 1873
1912 /// If this field is not `null`, this call is from an inlined constructor and 1874 /// If this field is not `null`, this call is from an inlined constructor and
1913 /// we have to register the instantiated type in the code generator. The 1875 /// we have to register the instantiated type in the code generator. The
1914 /// [instructionType] of this node is not enough, because we also need the 1876 /// [instructionType] of this node is not enough, because we also need the
1915 /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations]. 1877 /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
1916 List<DartType> instantiatedTypes; 1878 List<DartType> instantiatedTypes;
1917 1879
1918 HForeignNew(this.element, TypeMask type, List<HInstruction> inputs, 1880 HForeignNew(this.element, TypeMask type, List<HInstruction> inputs,
1919 [this.instantiatedTypes]) 1881 [this.instantiatedTypes])
1920 : super(type, inputs); 1882 : super(type, inputs);
1921 1883
1922 accept(HVisitor visitor) => visitor.visitForeignNew(this); 1884 accept(HVisitor visitor) => visitor.visitForeignNew(this);
1923 1885
1924 bool get isAllocation => true; 1886 bool get isAllocation => true;
1925 1887
1926 String toString() => 'HForeignNew($element)'; 1888 String toString() => 'HForeignNew($element)';
1927 } 1889 }
1928 1890
1929 abstract class HInvokeBinary extends HInstruction { 1891 abstract class HInvokeBinary extends HInstruction {
(...skipping 17 matching lines...) Expand all
1947 HInstruction left, HInstruction right, Selector selector, TypeMask type) 1909 HInstruction left, HInstruction right, Selector selector, TypeMask type)
1948 : super(left, right, selector, type); 1910 : super(left, right, selector, type);
1949 BinaryOperation operation(ConstantSystem constantSystem); 1911 BinaryOperation operation(ConstantSystem constantSystem);
1950 } 1912 }
1951 1913
1952 class HAdd extends HBinaryArithmetic { 1914 class HAdd extends HBinaryArithmetic {
1953 HAdd(HInstruction left, HInstruction right, Selector selector, TypeMask type) 1915 HAdd(HInstruction left, HInstruction right, Selector selector, TypeMask type)
1954 : super(left, right, selector, type); 1916 : super(left, right, selector, type);
1955 accept(HVisitor visitor) => visitor.visitAdd(this); 1917 accept(HVisitor visitor) => visitor.visitAdd(this);
1956 1918
1957 BinaryOperation operation(ConstantSystem constantSystem) 1919 BinaryOperation operation(ConstantSystem constantSystem) =>
1958 => constantSystem.add; 1920 constantSystem.add;
1959 int typeCode() => HInstruction.ADD_TYPECODE; 1921 int typeCode() => HInstruction.ADD_TYPECODE;
1960 bool typeEquals(other) => other is HAdd; 1922 bool typeEquals(other) => other is HAdd;
1961 bool dataEquals(HInstruction other) => true; 1923 bool dataEquals(HInstruction other) => true;
1962 } 1924 }
1963 1925
1964 class HDivide extends HBinaryArithmetic { 1926 class HDivide extends HBinaryArithmetic {
1965 HDivide( 1927 HDivide(
1966 HInstruction left, HInstruction right, Selector selector, TypeMask type) 1928 HInstruction left, HInstruction right, Selector selector, TypeMask type)
1967 : super(left, right, selector, type); 1929 : super(left, right, selector, type);
1968 accept(HVisitor visitor) => visitor.visitDivide(this); 1930 accept(HVisitor visitor) => visitor.visitDivide(this);
1969 1931
1970 BinaryOperation operation(ConstantSystem constantSystem) 1932 BinaryOperation operation(ConstantSystem constantSystem) =>
1971 => constantSystem.divide; 1933 constantSystem.divide;
1972 int typeCode() => HInstruction.DIVIDE_TYPECODE; 1934 int typeCode() => HInstruction.DIVIDE_TYPECODE;
1973 bool typeEquals(other) => other is HDivide; 1935 bool typeEquals(other) => other is HDivide;
1974 bool dataEquals(HInstruction other) => true; 1936 bool dataEquals(HInstruction other) => true;
1975 } 1937 }
1976 1938
1977 class HMultiply extends HBinaryArithmetic { 1939 class HMultiply extends HBinaryArithmetic {
1978 HMultiply( 1940 HMultiply(
1979 HInstruction left, HInstruction right, Selector selector, TypeMask type) 1941 HInstruction left, HInstruction right, Selector selector, TypeMask type)
1980 : super(left, right, selector, type); 1942 : super(left, right, selector, type);
1981 accept(HVisitor visitor) => visitor.visitMultiply(this); 1943 accept(HVisitor visitor) => visitor.visitMultiply(this);
1982 1944
1983 BinaryOperation operation(ConstantSystem operations) 1945 BinaryOperation operation(ConstantSystem operations) => operations.multiply;
1984 => operations.multiply;
1985 int typeCode() => HInstruction.MULTIPLY_TYPECODE; 1946 int typeCode() => HInstruction.MULTIPLY_TYPECODE;
1986 bool typeEquals(other) => other is HMultiply; 1947 bool typeEquals(other) => other is HMultiply;
1987 bool dataEquals(HInstruction other) => true; 1948 bool dataEquals(HInstruction other) => true;
1988 } 1949 }
1989 1950
1990 class HSubtract extends HBinaryArithmetic { 1951 class HSubtract extends HBinaryArithmetic {
1991 HSubtract( 1952 HSubtract(
1992 HInstruction left, HInstruction right, Selector selector, TypeMask type) 1953 HInstruction left, HInstruction right, Selector selector, TypeMask type)
1993 : super(left, right, selector, type); 1954 : super(left, right, selector, type);
1994 accept(HVisitor visitor) => visitor.visitSubtract(this); 1955 accept(HVisitor visitor) => visitor.visitSubtract(this);
1995 1956
1996 BinaryOperation operation(ConstantSystem constantSystem) 1957 BinaryOperation operation(ConstantSystem constantSystem) =>
1997 => constantSystem.subtract; 1958 constantSystem.subtract;
1998 int typeCode() => HInstruction.SUBTRACT_TYPECODE; 1959 int typeCode() => HInstruction.SUBTRACT_TYPECODE;
1999 bool typeEquals(other) => other is HSubtract; 1960 bool typeEquals(other) => other is HSubtract;
2000 bool dataEquals(HInstruction other) => true; 1961 bool dataEquals(HInstruction other) => true;
2001 } 1962 }
2002 1963
2003 class HTruncatingDivide extends HBinaryArithmetic { 1964 class HTruncatingDivide extends HBinaryArithmetic {
2004 HTruncatingDivide( 1965 HTruncatingDivide(
2005 HInstruction left, HInstruction right, Selector selector, TypeMask type) 1966 HInstruction left, HInstruction right, Selector selector, TypeMask type)
2006 : super(left, right, selector, type); 1967 : super(left, right, selector, type);
2007 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this); 1968 accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);
2008 1969
2009 BinaryOperation operation(ConstantSystem constantSystem) 1970 BinaryOperation operation(ConstantSystem constantSystem) =>
2010 => constantSystem.truncatingDivide; 1971 constantSystem.truncatingDivide;
2011 int typeCode() => HInstruction.TRUNCATING_DIVIDE_TYPECODE; 1972 int typeCode() => HInstruction.TRUNCATING_DIVIDE_TYPECODE;
2012 bool typeEquals(other) => other is HTruncatingDivide; 1973 bool typeEquals(other) => other is HTruncatingDivide;
2013 bool dataEquals(HInstruction other) => true; 1974 bool dataEquals(HInstruction other) => true;
2014 } 1975 }
2015 1976
2016 /** 1977 /**
2017 * An [HSwitch] instruction has one input for the incoming 1978 * An [HSwitch] instruction has one input for the incoming
2018 * value, and one input per constant that it can switch on. 1979 * value, and one input per constant that it can switch on.
2019 * Its block has one successor per constant, and one for the default. 1980 * Its block has one successor per constant, and one for the default.
2020 */ 1981 */
(...skipping 20 matching lines...) Expand all
2041 HInstruction left, HInstruction right, Selector selector, TypeMask type) 2002 HInstruction left, HInstruction right, Selector selector, TypeMask type)
2042 : super(left, right, selector, type); 2003 : super(left, right, selector, type);
2043 } 2004 }
2044 2005
2045 class HShiftLeft extends HBinaryBitOp { 2006 class HShiftLeft extends HBinaryBitOp {
2046 HShiftLeft( 2007 HShiftLeft(
2047 HInstruction left, HInstruction right, Selector selector, TypeMask type) 2008 HInstruction left, HInstruction right, Selector selector, TypeMask type)
2048 : super(left, right, selector, type); 2009 : super(left, right, selector, type);
2049 accept(HVisitor visitor) => visitor.visitShiftLeft(this); 2010 accept(HVisitor visitor) => visitor.visitShiftLeft(this);
2050 2011
2051 BinaryOperation operation(ConstantSystem constantSystem) 2012 BinaryOperation operation(ConstantSystem constantSystem) =>
2052 => constantSystem.shiftLeft; 2013 constantSystem.shiftLeft;
2053 int typeCode() => HInstruction.SHIFT_LEFT_TYPECODE; 2014 int typeCode() => HInstruction.SHIFT_LEFT_TYPECODE;
2054 bool typeEquals(other) => other is HShiftLeft; 2015 bool typeEquals(other) => other is HShiftLeft;
2055 bool dataEquals(HInstruction other) => true; 2016 bool dataEquals(HInstruction other) => true;
2056 } 2017 }
2057 2018
2058 class HShiftRight extends HBinaryBitOp { 2019 class HShiftRight extends HBinaryBitOp {
2059 HShiftRight( 2020 HShiftRight(
2060 HInstruction left, HInstruction right, Selector selector, TypeMask type) 2021 HInstruction left, HInstruction right, Selector selector, TypeMask type)
2061 : super(left, right, selector, type); 2022 : super(left, right, selector, type);
2062 accept(HVisitor visitor) => visitor.visitShiftRight(this); 2023 accept(HVisitor visitor) => visitor.visitShiftRight(this);
2063 2024
2064 BinaryOperation operation(ConstantSystem constantSystem) 2025 BinaryOperation operation(ConstantSystem constantSystem) =>
2065 => constantSystem.shiftRight; 2026 constantSystem.shiftRight;
2066 int typeCode() => HInstruction.SHIFT_RIGHT_TYPECODE; 2027 int typeCode() => HInstruction.SHIFT_RIGHT_TYPECODE;
2067 bool typeEquals(other) => other is HShiftRight; 2028 bool typeEquals(other) => other is HShiftRight;
2068 bool dataEquals(HInstruction other) => true; 2029 bool dataEquals(HInstruction other) => true;
2069 } 2030 }
2070 2031
2071 class HBitOr extends HBinaryBitOp { 2032 class HBitOr extends HBinaryBitOp {
2072 HBitOr( 2033 HBitOr(
2073 HInstruction left, HInstruction right, Selector selector, TypeMask type) 2034 HInstruction left, HInstruction right, Selector selector, TypeMask type)
2074 : super(left, right, selector, type); 2035 : super(left, right, selector, type);
2075 accept(HVisitor visitor) => visitor.visitBitOr(this); 2036 accept(HVisitor visitor) => visitor.visitBitOr(this);
2076 2037
2077 BinaryOperation operation(ConstantSystem constantSystem) 2038 BinaryOperation operation(ConstantSystem constantSystem) =>
2078 => constantSystem.bitOr; 2039 constantSystem.bitOr;
2079 int typeCode() => HInstruction.BIT_OR_TYPECODE; 2040 int typeCode() => HInstruction.BIT_OR_TYPECODE;
2080 bool typeEquals(other) => other is HBitOr; 2041 bool typeEquals(other) => other is HBitOr;
2081 bool dataEquals(HInstruction other) => true; 2042 bool dataEquals(HInstruction other) => true;
2082 } 2043 }
2083 2044
2084 class HBitAnd extends HBinaryBitOp { 2045 class HBitAnd extends HBinaryBitOp {
2085 HBitAnd( 2046 HBitAnd(
2086 HInstruction left, HInstruction right, Selector selector, TypeMask type) 2047 HInstruction left, HInstruction right, Selector selector, TypeMask type)
2087 : super(left, right, selector, type); 2048 : super(left, right, selector, type);
2088 accept(HVisitor visitor) => visitor.visitBitAnd(this); 2049 accept(HVisitor visitor) => visitor.visitBitAnd(this);
2089 2050
2090 BinaryOperation operation(ConstantSystem constantSystem) 2051 BinaryOperation operation(ConstantSystem constantSystem) =>
2091 => constantSystem.bitAnd; 2052 constantSystem.bitAnd;
2092 int typeCode() => HInstruction.BIT_AND_TYPECODE; 2053 int typeCode() => HInstruction.BIT_AND_TYPECODE;
2093 bool typeEquals(other) => other is HBitAnd; 2054 bool typeEquals(other) => other is HBitAnd;
2094 bool dataEquals(HInstruction other) => true; 2055 bool dataEquals(HInstruction other) => true;
2095 } 2056 }
2096 2057
2097 class HBitXor extends HBinaryBitOp { 2058 class HBitXor extends HBinaryBitOp {
2098 HBitXor( 2059 HBitXor(
2099 HInstruction left, HInstruction right, Selector selector, TypeMask type) 2060 HInstruction left, HInstruction right, Selector selector, TypeMask type)
2100 : super(left, right, selector, type); 2061 : super(left, right, selector, type);
2101 accept(HVisitor visitor) => visitor.visitBitXor(this); 2062 accept(HVisitor visitor) => visitor.visitBitXor(this);
2102 2063
2103 BinaryOperation operation(ConstantSystem constantSystem) 2064 BinaryOperation operation(ConstantSystem constantSystem) =>
2104 => constantSystem.bitXor; 2065 constantSystem.bitXor;
2105 int typeCode() => HInstruction.BIT_XOR_TYPECODE; 2066 int typeCode() => HInstruction.BIT_XOR_TYPECODE;
2106 bool typeEquals(other) => other is HBitXor; 2067 bool typeEquals(other) => other is HBitXor;
2107 bool dataEquals(HInstruction other) => true; 2068 bool dataEquals(HInstruction other) => true;
2108 } 2069 }
2109 2070
2110 abstract class HInvokeUnary extends HInstruction { 2071 abstract class HInvokeUnary extends HInstruction {
2111 final Selector selector; 2072 final Selector selector;
2112 HInvokeUnary(HInstruction input, this.selector, type) 2073 HInvokeUnary(HInstruction input, this.selector, type)
2113 : super(<HInstruction>[input], type) { 2074 : super(<HInstruction>[input], type) {
2114 sideEffects.clearAllSideEffects(); 2075 sideEffects.clearAllSideEffects();
2115 sideEffects.clearAllDependencies(); 2076 sideEffects.clearAllDependencies();
2116 setUseGvn(); 2077 setUseGvn();
2117 } 2078 }
2118 2079
2119 HInstruction get operand => inputs[0]; 2080 HInstruction get operand => inputs[0];
2120 2081
2121 UnaryOperation operation(ConstantSystem constantSystem); 2082 UnaryOperation operation(ConstantSystem constantSystem);
2122 } 2083 }
2123 2084
2124 class HNegate extends HInvokeUnary { 2085 class HNegate extends HInvokeUnary {
2125 HNegate(HInstruction input, Selector selector, TypeMask type) 2086 HNegate(HInstruction input, Selector selector, TypeMask type)
2126 : super(input, selector, type); 2087 : super(input, selector, type);
2127 accept(HVisitor visitor) => visitor.visitNegate(this); 2088 accept(HVisitor visitor) => visitor.visitNegate(this);
2128 2089
2129 UnaryOperation operation(ConstantSystem constantSystem) 2090 UnaryOperation operation(ConstantSystem constantSystem) =>
2130 => constantSystem.negate; 2091 constantSystem.negate;
2131 int typeCode() => HInstruction.NEGATE_TYPECODE; 2092 int typeCode() => HInstruction.NEGATE_TYPECODE;
2132 bool typeEquals(other) => other is HNegate; 2093 bool typeEquals(other) => other is HNegate;
2133 bool dataEquals(HInstruction other) => true; 2094 bool dataEquals(HInstruction other) => true;
2134 } 2095 }
2135 2096
2136 class HBitNot extends HInvokeUnary { 2097 class HBitNot extends HInvokeUnary {
2137 HBitNot(HInstruction input, Selector selector, TypeMask type) 2098 HBitNot(HInstruction input, Selector selector, TypeMask type)
2138 : super(input, selector, type); 2099 : super(input, selector, type);
2139 accept(HVisitor visitor) => visitor.visitBitNot(this); 2100 accept(HVisitor visitor) => visitor.visitBitNot(this);
2140 2101
2141 UnaryOperation operation(ConstantSystem constantSystem) 2102 UnaryOperation operation(ConstantSystem constantSystem) =>
2142 => constantSystem.bitNot; 2103 constantSystem.bitNot;
2143 int typeCode() => HInstruction.BIT_NOT_TYPECODE; 2104 int typeCode() => HInstruction.BIT_NOT_TYPECODE;
2144 bool typeEquals(other) => other is HBitNot; 2105 bool typeEquals(other) => other is HBitNot;
2145 bool dataEquals(HInstruction other) => true; 2106 bool dataEquals(HInstruction other) => true;
2146 } 2107 }
2147 2108
2148 class HExit extends HControlFlow { 2109 class HExit extends HControlFlow {
2149 HExit() : super(const <HInstruction>[]); 2110 HExit() : super(const <HInstruction>[]);
2150 toString() => 'exit'; 2111 toString() => 'exit';
2151 accept(HVisitor visitor) => visitor.visitExit(this); 2112 accept(HVisitor visitor) => visitor.visitExit(this);
2152 } 2113 }
2153 2114
2154 class HGoto extends HControlFlow { 2115 class HGoto extends HControlFlow {
2155 HGoto() : super(const <HInstruction>[]); 2116 HGoto() : super(const <HInstruction>[]);
2156 toString() => 'goto'; 2117 toString() => 'goto';
2157 accept(HVisitor visitor) => visitor.visitGoto(this); 2118 accept(HVisitor visitor) => visitor.visitGoto(this);
2158 } 2119 }
2159 2120
2160 abstract class HJump extends HControlFlow { 2121 abstract class HJump extends HControlFlow {
2161 final JumpTarget target; 2122 final JumpTarget target;
2162 final LabelDefinition label; 2123 final LabelDefinition label;
2163 HJump(this.target) : label = null, super(const <HInstruction>[]); 2124 HJump(this.target)
2125 : label = null,
2126 super(const <HInstruction>[]);
2164 HJump.toLabel(LabelDefinition label) 2127 HJump.toLabel(LabelDefinition label)
2165 : label = label, target = label.target, super(const <HInstruction>[]); 2128 : label = label,
2129 target = label.target,
2130 super(const <HInstruction>[]);
2166 } 2131 }
2167 2132
2168 class HBreak extends HJump { 2133 class HBreak extends HJump {
2169 /** 2134 /**
2170 * Signals that this is a special break instruction for the synthetic loop 2135 * Signals that this is a special break instruction for the synthetic loop
2171 * generatedfor a switch statement with continue statements. See 2136 * generatedfor a switch statement with continue statements. See
2172 * [SsaFromAstMixin.buildComplexSwitchStatement] for detail. 2137 * [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
2173 */ 2138 */
2174 final bool breakSwitchContinueLoop; 2139 final bool breakSwitchContinueLoop;
2175 HBreak(JumpTarget target, {bool this.breakSwitchContinueLoop: false}) 2140 HBreak(JumpTarget target, {bool this.breakSwitchContinueLoop: false})
2176 : super(target); 2141 : super(target);
2177 HBreak.toLabel(LabelDefinition label) 2142 HBreak.toLabel(LabelDefinition label)
2178 : breakSwitchContinueLoop = false, super.toLabel(label); 2143 : breakSwitchContinueLoop = false,
2144 super.toLabel(label);
2179 toString() => (label != null) ? 'break ${label.labelName}' : 'break'; 2145 toString() => (label != null) ? 'break ${label.labelName}' : 'break';
2180 accept(HVisitor visitor) => visitor.visitBreak(this); 2146 accept(HVisitor visitor) => visitor.visitBreak(this);
2181 } 2147 }
2182 2148
2183 class HContinue extends HJump { 2149 class HContinue extends HJump {
2184 HContinue(JumpTarget target) : super(target); 2150 HContinue(JumpTarget target) : super(target);
2185 HContinue.toLabel(LabelDefinition label) : super.toLabel(label); 2151 HContinue.toLabel(LabelDefinition label) : super.toLabel(label);
2186 toString() => (label != null) ? 'continue ${label.labelName}' : 'continue'; 2152 toString() => (label != null) ? 'continue ${label.labelName}' : 'continue';
2187 accept(HVisitor visitor) => visitor.visitContinue(this); 2153 accept(HVisitor visitor) => visitor.visitContinue(this);
2188 } 2154 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
2282 bool typeEquals(other) => other is HNot; 2248 bool typeEquals(other) => other is HNot;
2283 bool dataEquals(HInstruction other) => true; 2249 bool dataEquals(HInstruction other) => true;
2284 } 2250 }
2285 2251
2286 /** 2252 /**
2287 * An [HLocalValue] represents a local. Unlike [HParameterValue]s its 2253 * An [HLocalValue] represents a local. Unlike [HParameterValue]s its
2288 * first use must be in an HLocalSet. That is, [HParameterValue]s have a 2254 * first use must be in an HLocalSet. That is, [HParameterValue]s have a
2289 * value from the start, whereas [HLocalValue]s need to be initialized first. 2255 * value from the start, whereas [HLocalValue]s need to be initialized first.
2290 */ 2256 */
2291 class HLocalValue extends HInstruction { 2257 class HLocalValue extends HInstruction {
2292 HLocalValue(Entity variable, TypeMask type) 2258 HLocalValue(Entity variable, TypeMask type) : super(<HInstruction>[], type) {
2293 : super(<HInstruction>[], type) {
2294 sourceElement = variable; 2259 sourceElement = variable;
2295 } 2260 }
2296 2261
2297 toString() => 'local ${sourceElement.name}'; 2262 toString() => 'local ${sourceElement.name}';
2298 accept(HVisitor visitor) => visitor.visitLocalValue(this); 2263 accept(HVisitor visitor) => visitor.visitLocalValue(this);
2299 } 2264 }
2300 2265
2301 class HParameterValue extends HLocalValue { 2266 class HParameterValue extends HLocalValue {
2302 HParameterValue(Entity variable, type) : super(variable, type); 2267 HParameterValue(Entity variable, type) : super(variable, type);
2303 2268
(...skipping 29 matching lines...) Expand all
2333 // predecessor-edges. That is if an input comes from the first predecessor 2298 // predecessor-edges. That is if an input comes from the first predecessor
2334 // of the surrounding block, then the input must be the first in the [HPhi]. 2299 // of the surrounding block, then the input must be the first in the [HPhi].
2335 HPhi(Local variable, List<HInstruction> inputs, TypeMask type) 2300 HPhi(Local variable, List<HInstruction> inputs, TypeMask type)
2336 : super(inputs, type) { 2301 : super(inputs, type) {
2337 sourceElement = variable; 2302 sourceElement = variable;
2338 } 2303 }
2339 HPhi.noInputs(Local variable, TypeMask type) 2304 HPhi.noInputs(Local variable, TypeMask type)
2340 : this(variable, <HInstruction>[], type); 2305 : this(variable, <HInstruction>[], type);
2341 HPhi.singleInput(Local variable, HInstruction input, TypeMask type) 2306 HPhi.singleInput(Local variable, HInstruction input, TypeMask type)
2342 : this(variable, <HInstruction>[input], type); 2307 : this(variable, <HInstruction>[input], type);
2343 HPhi.manyInputs(Local variable, 2308 HPhi.manyInputs(Local variable, List<HInstruction> inputs, TypeMask type)
2344 List<HInstruction> inputs,
2345 TypeMask type)
2346 : this(variable, inputs, type); 2309 : this(variable, inputs, type);
2347 2310
2348 void addInput(HInstruction input) { 2311 void addInput(HInstruction input) {
2349 assert(isInBasicBlock()); 2312 assert(isInBasicBlock());
2350 inputs.add(input); 2313 inputs.add(input);
2351 assert(inputs.length <= block.predecessors.length); 2314 assert(inputs.length <= block.predecessors.length);
2352 input.usedBy.add(this); 2315 input.usedBy.add(this);
2353 } 2316 }
2354 2317
2355 toString() => 'phi $id'; 2318 toString() => 'phi $id';
2356 accept(HVisitor visitor) => visitor.visitPhi(this); 2319 accept(HVisitor visitor) => visitor.visitPhi(this);
2357 } 2320 }
2358 2321
2359 abstract class HRelational extends HInvokeBinary { 2322 abstract class HRelational extends HInvokeBinary {
2360 bool usesBoolifiedInterceptor = false; 2323 bool usesBoolifiedInterceptor = false;
2361 HRelational(left, right, selector, type) : super(left, right, selector, type); 2324 HRelational(left, right, selector, type) : super(left, right, selector, type);
2362 } 2325 }
2363 2326
2364 class HIdentity extends HRelational { 2327 class HIdentity extends HRelational {
2365 // Cached codegen decision. 2328 // Cached codegen decision.
2366 String singleComparisonOp; // null, '===', '==' 2329 String singleComparisonOp; // null, '===', '=='
2367 2330
2368 HIdentity(left, right, selector, type) : super(left, right, selector, type); 2331 HIdentity(left, right, selector, type) : super(left, right, selector, type);
2369 accept(HVisitor visitor) => visitor.visitIdentity(this); 2332 accept(HVisitor visitor) => visitor.visitIdentity(this);
2370 2333
2371 BinaryOperation operation(ConstantSystem constantSystem) 2334 BinaryOperation operation(ConstantSystem constantSystem) =>
2372 => constantSystem.identity; 2335 constantSystem.identity;
2373 int typeCode() => HInstruction.IDENTITY_TYPECODE; 2336 int typeCode() => HInstruction.IDENTITY_TYPECODE;
2374 bool typeEquals(other) => other is HIdentity; 2337 bool typeEquals(other) => other is HIdentity;
2375 bool dataEquals(HInstruction other) => true; 2338 bool dataEquals(HInstruction other) => true;
2376 } 2339 }
2377 2340
2378 class HGreater extends HRelational { 2341 class HGreater extends HRelational {
2379 HGreater(left, right, selector, type) : super(left, right, selector, type); 2342 HGreater(left, right, selector, type) : super(left, right, selector, type);
2380 accept(HVisitor visitor) => visitor.visitGreater(this); 2343 accept(HVisitor visitor) => visitor.visitGreater(this);
2381 2344
2382 BinaryOperation operation(ConstantSystem constantSystem) 2345 BinaryOperation operation(ConstantSystem constantSystem) =>
2383 => constantSystem.greater; 2346 constantSystem.greater;
2384 int typeCode() => HInstruction.GREATER_TYPECODE; 2347 int typeCode() => HInstruction.GREATER_TYPECODE;
2385 bool typeEquals(other) => other is HGreater; 2348 bool typeEquals(other) => other is HGreater;
2386 bool dataEquals(HInstruction other) => true; 2349 bool dataEquals(HInstruction other) => true;
2387 } 2350 }
2388 2351
2389 class HGreaterEqual extends HRelational { 2352 class HGreaterEqual extends HRelational {
2390 HGreaterEqual(left, right, selector, type) 2353 HGreaterEqual(left, right, selector, type)
2391 : super(left, right, selector, type); 2354 : super(left, right, selector, type);
2392 accept(HVisitor visitor) => visitor.visitGreaterEqual(this); 2355 accept(HVisitor visitor) => visitor.visitGreaterEqual(this);
2393 2356
2394 BinaryOperation operation(ConstantSystem constantSystem) 2357 BinaryOperation operation(ConstantSystem constantSystem) =>
2395 => constantSystem.greaterEqual; 2358 constantSystem.greaterEqual;
2396 int typeCode() => HInstruction.GREATER_EQUAL_TYPECODE; 2359 int typeCode() => HInstruction.GREATER_EQUAL_TYPECODE;
2397 bool typeEquals(other) => other is HGreaterEqual; 2360 bool typeEquals(other) => other is HGreaterEqual;
2398 bool dataEquals(HInstruction other) => true; 2361 bool dataEquals(HInstruction other) => true;
2399 } 2362 }
2400 2363
2401 class HLess extends HRelational { 2364 class HLess extends HRelational {
2402 HLess(left, right, selector, type) : super(left, right, selector, type); 2365 HLess(left, right, selector, type) : super(left, right, selector, type);
2403 accept(HVisitor visitor) => visitor.visitLess(this); 2366 accept(HVisitor visitor) => visitor.visitLess(this);
2404 2367
2405 BinaryOperation operation(ConstantSystem constantSystem) 2368 BinaryOperation operation(ConstantSystem constantSystem) =>
2406 => constantSystem.less; 2369 constantSystem.less;
2407 int typeCode() => HInstruction.LESS_TYPECODE; 2370 int typeCode() => HInstruction.LESS_TYPECODE;
2408 bool typeEquals(other) => other is HLess; 2371 bool typeEquals(other) => other is HLess;
2409 bool dataEquals(HInstruction other) => true; 2372 bool dataEquals(HInstruction other) => true;
2410 } 2373 }
2411 2374
2412 class HLessEqual extends HRelational { 2375 class HLessEqual extends HRelational {
2413 HLessEqual(left, right, selector, type) : super(left, right, selector, type); 2376 HLessEqual(left, right, selector, type) : super(left, right, selector, type);
2414 accept(HVisitor visitor) => visitor.visitLessEqual(this); 2377 accept(HVisitor visitor) => visitor.visitLessEqual(this);
2415 2378
2416 BinaryOperation operation(ConstantSystem constantSystem) 2379 BinaryOperation operation(ConstantSystem constantSystem) =>
2417 => constantSystem.lessEqual; 2380 constantSystem.lessEqual;
2418 int typeCode() => HInstruction.LESS_EQUAL_TYPECODE; 2381 int typeCode() => HInstruction.LESS_EQUAL_TYPECODE;
2419 bool typeEquals(other) => other is HLessEqual; 2382 bool typeEquals(other) => other is HLessEqual;
2420 bool dataEquals(HInstruction other) => true; 2383 bool dataEquals(HInstruction other) => true;
2421 } 2384 }
2422 2385
2423 class HReturn extends HControlFlow { 2386 class HReturn extends HControlFlow {
2424 HReturn(HInstruction value, SourceInformation sourceInformation) 2387 HReturn(HInstruction value, SourceInformation sourceInformation)
2425 : super(<HInstruction>[value]) { 2388 : super(<HInstruction>[value]) {
2426 this.sourceInformation = sourceInformation; 2389 this.sourceInformation = sourceInformation;
2427 } 2390 }
(...skipping 26 matching lines...) Expand all
2454 : super(<HInstruction>[value], const TypeMask.nonNullEmpty()); 2417 : super(<HInstruction>[value], const TypeMask.nonNullEmpty());
2455 bool hasStar; 2418 bool hasStar;
2456 toString() => 'yield'; 2419 toString() => 'yield';
2457 accept(HVisitor visitor) => visitor.visitYield(this); 2420 accept(HVisitor visitor) => visitor.visitYield(this);
2458 bool canThrow() => false; 2421 bool canThrow() => false;
2459 SideEffects sideEffects = new SideEffects(); 2422 SideEffects sideEffects = new SideEffects();
2460 } 2423 }
2461 2424
2462 class HThrow extends HControlFlow { 2425 class HThrow extends HControlFlow {
2463 final bool isRethrow; 2426 final bool isRethrow;
2464 HThrow(HInstruction value, 2427 HThrow(HInstruction value, SourceInformation sourceInformation,
2465 SourceInformation sourceInformation, 2428 {this.isRethrow: false})
2466 {this.isRethrow: false})
2467 : super(<HInstruction>[value]) { 2429 : super(<HInstruction>[value]) {
2468 this.sourceInformation = sourceInformation; 2430 this.sourceInformation = sourceInformation;
2469 } 2431 }
2470 toString() => 'throw'; 2432 toString() => 'throw';
2471 accept(HVisitor visitor) => visitor.visitThrow(this); 2433 accept(HVisitor visitor) => visitor.visitThrow(this);
2472 } 2434 }
2473 2435
2474 class HStatic extends HInstruction { 2436 class HStatic extends HInstruction {
2475 final Element element; 2437 final Element element;
2476 HStatic(this.element, type) : super(<HInstruction>[], type) { 2438 HStatic(this.element, type) : super(<HInstruction>[], type) {
(...skipping 23 matching lines...) Expand all
2500 2462
2501 // inputs[0] is initially the only input, the receiver. 2463 // inputs[0] is initially the only input, the receiver.
2502 2464
2503 // inputs[1] is a constant interceptor when the interceptor is a constant 2465 // inputs[1] is a constant interceptor when the interceptor is a constant
2504 // except for a `null` receiver. This is used when the receiver can't be 2466 // except for a `null` receiver. This is used when the receiver can't be
2505 // falsy, except for `null`, allowing the generation of code like 2467 // falsy, except for `null`, allowing the generation of code like
2506 // 2468 //
2507 // (a && C.JSArray_methods).get$first(a) 2469 // (a && C.JSArray_methods).get$first(a)
2508 // 2470 //
2509 2471
2510 HInterceptor(HInstruction receiver, 2472 HInterceptor(HInstruction receiver, TypeMask type)
2511 TypeMask type)
2512 : super(<HInstruction>[receiver], type) { 2473 : super(<HInstruction>[receiver], type) {
2513 this.sourceInformation = receiver.sourceInformation; 2474 this.sourceInformation = receiver.sourceInformation;
2514 sideEffects.clearAllSideEffects(); 2475 sideEffects.clearAllSideEffects();
2515 sideEffects.clearAllDependencies(); 2476 sideEffects.clearAllDependencies();
2516 setUseGvn(); 2477 setUseGvn();
2517 } 2478 }
2518 2479
2519 String toString() => 'interceptor on $interceptedClasses'; 2480 String toString() => 'interceptor on $interceptedClasses';
2520 accept(HVisitor visitor) => visitor.visitInterceptor(this); 2481 accept(HVisitor visitor) => visitor.visitInterceptor(this);
2521 HInstruction get receiver => inputs[0]; 2482 HInstruction get receiver => inputs[0];
2522 2483
2523 bool get isConditionalConstantInterceptor => inputs.length == 2; 2484 bool get isConditionalConstantInterceptor => inputs.length == 2;
2524 HInstruction get conditionalConstantInterceptor => inputs[1]; 2485 HInstruction get conditionalConstantInterceptor => inputs[1];
2525 void set conditionalConstantInterceptor(HConstant constant) { 2486 void set conditionalConstantInterceptor(HConstant constant) {
2526 assert(!isConditionalConstantInterceptor); 2487 assert(!isConditionalConstantInterceptor);
2527 inputs.add(constant); 2488 inputs.add(constant);
2528 } 2489 }
2529 2490
2530 bool isInterceptor(Compiler compiler) => true; 2491 bool isInterceptor(Compiler compiler) => true;
2531 2492
2532 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE; 2493 int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
2533 bool typeEquals(other) => other is HInterceptor; 2494 bool typeEquals(other) => other is HInterceptor;
2534 bool dataEquals(HInterceptor other) { 2495 bool dataEquals(HInterceptor other) {
2535 return interceptedClasses == other.interceptedClasses 2496 return interceptedClasses == other.interceptedClasses ||
2536 || (interceptedClasses.length == other.interceptedClasses.length 2497 (interceptedClasses.length == other.interceptedClasses.length &&
2537 && interceptedClasses.containsAll(other.interceptedClasses)); 2498 interceptedClasses.containsAll(other.interceptedClasses));
2538 } 2499 }
2539 } 2500 }
2540 2501
2541 /** 2502 /**
2542 * A "one-shot" interceptor is a call to a synthetized method that 2503 * A "one-shot" interceptor is a call to a synthetized method that
2543 * will fetch the interceptor of its first parameter, and make a call 2504 * will fetch the interceptor of its first parameter, and make a call
2544 * on a given selector with the remaining parameters. 2505 * on a given selector with the remaining parameters.
2545 * 2506 *
2546 * In order to share the same optimizations with regular interceptor 2507 * In order to share the same optimizations with regular interceptor
2547 * calls, this class extends [HInvokeDynamic] and also has the null 2508 * calls, this class extends [HInvokeDynamic] and also has the null
2548 * constant as the first input. 2509 * constant as the first input.
2549 */ 2510 */
2550 class HOneShotInterceptor extends HInvokeDynamic { 2511 class HOneShotInterceptor extends HInvokeDynamic {
2551 Set<ClassElement> interceptedClasses; 2512 Set<ClassElement> interceptedClasses;
2552 HOneShotInterceptor(Selector selector, 2513 HOneShotInterceptor(Selector selector, TypeMask mask,
2553 TypeMask mask, 2514 List<HInstruction> inputs, TypeMask type, this.interceptedClasses)
2554 List<HInstruction> inputs,
2555 TypeMask type,
2556 this.interceptedClasses)
2557 : super(selector, mask, null, inputs, type, true) { 2515 : super(selector, mask, null, inputs, type, true) {
2558 assert(inputs[0] is HConstant); 2516 assert(inputs[0] is HConstant);
2559 assert(inputs[0].isNull()); 2517 assert(inputs[0].isNull());
2560 } 2518 }
2561 bool isCallOnInterceptor(Compiler compiler) => true; 2519 bool isCallOnInterceptor(Compiler compiler) => true;
2562 2520
2563 String toString() => 'one shot interceptor: selector=$selector, mask=$mask'; 2521 String toString() => 'one shot interceptor: selector=$selector, mask=$mask';
2564 accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this); 2522 accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
2565 } 2523 }
2566 2524
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2607 2565
2608 bool get isAllocation => true; 2566 bool get isAllocation => true;
2609 } 2567 }
2610 2568
2611 /** 2569 /**
2612 * The primitive array indexing operation. Note that this instruction 2570 * The primitive array indexing operation. Note that this instruction
2613 * does not throw because we generate the checks explicitly. 2571 * does not throw because we generate the checks explicitly.
2614 */ 2572 */
2615 class HIndex extends HInstruction { 2573 class HIndex extends HInstruction {
2616 final Selector selector; 2574 final Selector selector;
2617 HIndex(HInstruction receiver, 2575 HIndex(
2618 HInstruction index, 2576 HInstruction receiver, HInstruction index, this.selector, TypeMask type)
2619 this.selector,
2620 TypeMask type)
2621 : super(<HInstruction>[receiver, index], type) { 2577 : super(<HInstruction>[receiver, index], type) {
2622 sideEffects.clearAllSideEffects(); 2578 sideEffects.clearAllSideEffects();
2623 sideEffects.clearAllDependencies(); 2579 sideEffects.clearAllDependencies();
2624 sideEffects.setDependsOnIndexStore(); 2580 sideEffects.setDependsOnIndexStore();
2625 setUseGvn(); 2581 setUseGvn();
2626 } 2582 }
2627 2583
2628 String toString() => 'index operator'; 2584 String toString() => 'index operator';
2629 accept(HVisitor visitor) => visitor.visitIndex(this); 2585 accept(HVisitor visitor) => visitor.visitIndex(this);
2630 2586
2631 HInstruction get receiver => inputs[0]; 2587 HInstruction get receiver => inputs[0];
2632 HInstruction get index => inputs[1]; 2588 HInstruction get index => inputs[1];
2633 2589
2634 HInstruction getDartReceiver(Compiler compiler) => receiver; 2590 HInstruction getDartReceiver(Compiler compiler) => receiver;
2635 bool onlyThrowsNSM() => true; 2591 bool onlyThrowsNSM() => true;
2636 bool canThrow() => receiver.canBeNull(); 2592 bool canThrow() => receiver.canBeNull();
2637 2593
2638 int typeCode() => HInstruction.INDEX_TYPECODE; 2594 int typeCode() => HInstruction.INDEX_TYPECODE;
2639 bool typeEquals(HInstruction other) => other is HIndex; 2595 bool typeEquals(HInstruction other) => other is HIndex;
2640 bool dataEquals(HIndex other) => true; 2596 bool dataEquals(HIndex other) => true;
2641 } 2597 }
2642 2598
2643 /** 2599 /**
2644 * The primitive array assignment operation. Note that this instruction 2600 * The primitive array assignment operation. Note that this instruction
2645 * does not throw because we generate the checks explicitly. 2601 * does not throw because we generate the checks explicitly.
2646 */ 2602 */
2647 class HIndexAssign extends HInstruction { 2603 class HIndexAssign extends HInstruction {
2648 final Selector selector; 2604 final Selector selector;
2649 HIndexAssign(HInstruction receiver, 2605 HIndexAssign(HInstruction receiver, HInstruction index, HInstruction value,
2650 HInstruction index, 2606 this.selector)
2651 HInstruction value,
2652 this.selector)
2653 : super(<HInstruction>[receiver, index, value], 2607 : super(<HInstruction>[receiver, index, value],
2654 const TypeMask.nonNullEmpty()) { 2608 const TypeMask.nonNullEmpty()) {
2655 sideEffects.clearAllSideEffects(); 2609 sideEffects.clearAllSideEffects();
2656 sideEffects.clearAllDependencies(); 2610 sideEffects.clearAllDependencies();
2657 sideEffects.setChangesIndex(); 2611 sideEffects.setChangesIndex();
2658 } 2612 }
2659 String toString() => 'index assign operator'; 2613 String toString() => 'index assign operator';
2660 accept(HVisitor visitor) => visitor.visitIndexAssign(this); 2614 accept(HVisitor visitor) => visitor.visitIndexAssign(this);
2661 2615
2662 HInstruction get receiver => inputs[0]; 2616 HInstruction get receiver => inputs[0];
2663 HInstruction get index => inputs[1]; 2617 HInstruction get index => inputs[1];
2664 HInstruction get value => inputs[2]; 2618 HInstruction get value => inputs[2];
2665 2619
2666 HInstruction getDartReceiver(Compiler compiler) => receiver; 2620 HInstruction getDartReceiver(Compiler compiler) => receiver;
2667 bool onlyThrowsNSM() => true; 2621 bool onlyThrowsNSM() => true;
2668 bool canThrow() => receiver.canBeNull(); 2622 bool canThrow() => receiver.canBeNull();
2669 } 2623 }
2670 2624
2671 class HIs extends HInstruction { 2625 class HIs extends HInstruction {
2672 /// A check against a raw type: 'o is int', 'o is A'. 2626 /// A check against a raw type: 'o is int', 'o is A'.
2673 static const int RAW_CHECK = 0; 2627 static const int RAW_CHECK = 0;
2628
2674 /// A check against a type with type arguments: 'o is List<int>', 'o is C<T>'. 2629 /// A check against a type with type arguments: 'o is List<int>', 'o is C<T>'.
2675 static const int COMPOUND_CHECK = 1; 2630 static const int COMPOUND_CHECK = 1;
2631
2676 /// A check against a single type variable: 'o is T'. 2632 /// A check against a single type variable: 'o is T'.
2677 static const int VARIABLE_CHECK = 2; 2633 static const int VARIABLE_CHECK = 2;
2678 2634
2679 final DartType typeExpression; 2635 final DartType typeExpression;
2680 final int kind; 2636 final int kind;
2681 final bool useInstanceOf; 2637 final bool useInstanceOf;
2682 2638
2683 HIs.direct(DartType typeExpression, 2639 HIs.direct(DartType typeExpression, HInstruction expression, TypeMask type)
2684 HInstruction expression,
2685 TypeMask type)
2686 : this.internal(typeExpression, [expression], RAW_CHECK, type); 2640 : this.internal(typeExpression, [expression], RAW_CHECK, type);
2687 2641
2688 // Pre-verified that the check can be done using 'instanceof'. 2642 // Pre-verified that the check can be done using 'instanceof'.
2689 HIs.instanceOf(DartType typeExpression, 2643 HIs.instanceOf(
2690 HInstruction expression, 2644 DartType typeExpression, HInstruction expression, TypeMask type)
2691 TypeMask type)
2692 : this.internal(typeExpression, [expression], RAW_CHECK, type, 2645 : this.internal(typeExpression, [expression], RAW_CHECK, type,
2693 useInstanceOf: true); 2646 useInstanceOf: true);
2694 2647
2695 HIs.raw(DartType typeExpression, 2648 HIs.raw(DartType typeExpression, HInstruction expression,
2696 HInstruction expression, 2649 HInterceptor interceptor, TypeMask type)
2697 HInterceptor interceptor,
2698 TypeMask type)
2699 : this.internal( 2650 : this.internal(
2700 typeExpression, [expression, interceptor], RAW_CHECK, type); 2651 typeExpression, [expression, interceptor], RAW_CHECK, type);
2701 2652
2702 HIs.compound(DartType typeExpression, 2653 HIs.compound(DartType typeExpression, HInstruction expression,
2703 HInstruction expression, 2654 HInstruction call, TypeMask type)
2704 HInstruction call,
2705 TypeMask type)
2706 : this.internal(typeExpression, [expression, call], COMPOUND_CHECK, type); 2655 : this.internal(typeExpression, [expression, call], COMPOUND_CHECK, type);
2707 2656
2708 HIs.variable(DartType typeExpression, 2657 HIs.variable(DartType typeExpression, HInstruction expression,
2709 HInstruction expression, 2658 HInstruction call, TypeMask type)
2710 HInstruction call,
2711 TypeMask type)
2712 : this.internal(typeExpression, [expression, call], VARIABLE_CHECK, type); 2659 : this.internal(typeExpression, [expression, call], VARIABLE_CHECK, type);
2713 2660
2714 HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind, 2661 HIs.internal(
2715 TypeMask type, {bool this.useInstanceOf: false}) 2662 this.typeExpression, List<HInstruction> inputs, this.kind, TypeMask type,
2663 {bool this.useInstanceOf: false})
2716 : super(inputs, type) { 2664 : super(inputs, type) {
2717 assert(kind >= RAW_CHECK && kind <= VARIABLE_CHECK); 2665 assert(kind >= RAW_CHECK && kind <= VARIABLE_CHECK);
2718 setUseGvn(); 2666 setUseGvn();
2719 } 2667 }
2720 2668
2721 HInstruction get expression => inputs[0]; 2669 HInstruction get expression => inputs[0];
2722 2670
2723 HInstruction get interceptor { 2671 HInstruction get interceptor {
2724 assert(kind == RAW_CHECK); 2672 assert(kind == RAW_CHECK);
2725 return inputs.length > 1 ? inputs[1] : null; 2673 return inputs.length > 1 ? inputs[1] : null;
(...skipping 10 matching lines...) Expand all
2736 2684
2737 accept(HVisitor visitor) => visitor.visitIs(this); 2685 accept(HVisitor visitor) => visitor.visitIs(this);
2738 2686
2739 toString() => "$expression is $typeExpression"; 2687 toString() => "$expression is $typeExpression";
2740 2688
2741 int typeCode() => HInstruction.IS_TYPECODE; 2689 int typeCode() => HInstruction.IS_TYPECODE;
2742 2690
2743 bool typeEquals(HInstruction other) => other is HIs; 2691 bool typeEquals(HInstruction other) => other is HIs;
2744 2692
2745 bool dataEquals(HIs other) { 2693 bool dataEquals(HIs other) {
2746 return typeExpression == other.typeExpression 2694 return typeExpression == other.typeExpression && kind == other.kind;
2747 && kind == other.kind;
2748 } 2695 }
2749 } 2696 }
2750 2697
2751 /** 2698 /**
2752 * HIsViaInterceptor is a late-stage instruction for a type test that can be 2699 * HIsViaInterceptor is a late-stage instruction for a type test that can be
2753 * done entirely on an interceptor. It is not a HCheck because the checked 2700 * done entirely on an interceptor. It is not a HCheck because the checked
2754 * input is not one of the inputs. 2701 * input is not one of the inputs.
2755 */ 2702 */
2756 class HIsViaInterceptor extends HLateInstruction { 2703 class HIsViaInterceptor extends HLateInstruction {
2757 final DartType typeExpression; 2704 final DartType typeExpression;
2758 HIsViaInterceptor(this.typeExpression, HInstruction interceptor, 2705 HIsViaInterceptor(
2759 TypeMask type) 2706 this.typeExpression, HInstruction interceptor, TypeMask type)
2760 : super(<HInstruction>[interceptor], type) { 2707 : super(<HInstruction>[interceptor], type) {
2761 setUseGvn(); 2708 setUseGvn();
2762 } 2709 }
2763 2710
2764 HInstruction get interceptor => inputs[0]; 2711 HInstruction get interceptor => inputs[0];
2765 2712
2766 accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this); 2713 accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this);
2767 toString() => "$interceptor is $typeExpression"; 2714 toString() => "$interceptor is $typeExpression";
2768 int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE; 2715 int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE;
2769 bool typeEquals(HInstruction other) => other is HIsViaInterceptor; 2716 bool typeEquals(HInstruction other) => other is HIsViaInterceptor;
2770 bool dataEquals(HIs other) { 2717 bool dataEquals(HIs other) {
2771 return typeExpression == other.typeExpression; 2718 return typeExpression == other.typeExpression;
2772 } 2719 }
2773 } 2720 }
2774 2721
2775 class HTypeConversion extends HCheck { 2722 class HTypeConversion extends HCheck {
2776 final DartType typeExpression; 2723 final DartType typeExpression;
2777 final int kind; 2724 final int kind;
2778 final Selector receiverTypeCheckSelector; 2725 final Selector receiverTypeCheckSelector;
2779 final bool contextIsTypeArguments; 2726 final bool contextIsTypeArguments;
2780 TypeMask checkedType; // Not final because we refine it. 2727 TypeMask checkedType; // Not final because we refine it.
2781 2728
2782 static const int CHECKED_MODE_CHECK = 0; 2729 static const int CHECKED_MODE_CHECK = 0;
2783 static const int ARGUMENT_TYPE_CHECK = 1; 2730 static const int ARGUMENT_TYPE_CHECK = 1;
2784 static const int CAST_TYPE_CHECK = 2; 2731 static const int CAST_TYPE_CHECK = 2;
2785 static const int BOOLEAN_CONVERSION_CHECK = 3; 2732 static const int BOOLEAN_CONVERSION_CHECK = 3;
2786 static const int RECEIVER_TYPE_CHECK = 4; 2733 static const int RECEIVER_TYPE_CHECK = 4;
2787 2734
2788 HTypeConversion(this.typeExpression, this.kind, 2735 HTypeConversion(
2789 TypeMask type, HInstruction input, 2736 this.typeExpression, this.kind, TypeMask type, HInstruction input,
2790 [this.receiverTypeCheckSelector]) 2737 [this.receiverTypeCheckSelector])
2791 : contextIsTypeArguments = false, 2738 : contextIsTypeArguments = false,
2792 checkedType = type, 2739 checkedType = type,
2793 super(<HInstruction>[input], type) { 2740 super(<HInstruction>[input], type) {
2794 assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null); 2741 assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
2795 assert(typeExpression == null || 2742 assert(typeExpression == null || typeExpression.kind != TypeKind.TYPEDEF);
2796 typeExpression.kind != TypeKind.TYPEDEF);
2797 sourceElement = input.sourceElement; 2743 sourceElement = input.sourceElement;
2798 } 2744 }
2799 2745
2800 HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind, 2746 HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
2801 TypeMask type, HInstruction input, 2747 TypeMask type, HInstruction input, HInstruction typeRepresentation)
2802 HInstruction typeRepresentation)
2803 : contextIsTypeArguments = false, 2748 : contextIsTypeArguments = false,
2804 checkedType = type, 2749 checkedType = type,
2805 super(<HInstruction>[input, typeRepresentation],type), 2750 super(<HInstruction>[input, typeRepresentation], type),
2806 receiverTypeCheckSelector = null { 2751 receiverTypeCheckSelector = null {
2807 assert(typeExpression.kind != TypeKind.TYPEDEF); 2752 assert(typeExpression.kind != TypeKind.TYPEDEF);
2808 sourceElement = input.sourceElement; 2753 sourceElement = input.sourceElement;
2809 } 2754 }
2810 2755
2811 HTypeConversion.withContext(this.typeExpression, this.kind, 2756 HTypeConversion.withContext(this.typeExpression, this.kind, TypeMask type,
2812 TypeMask type, HInstruction input, 2757 HInstruction input, HInstruction context,
2813 HInstruction context, 2758 {bool this.contextIsTypeArguments})
2814 {bool this.contextIsTypeArguments})
2815 : super(<HInstruction>[input, context], type), 2759 : super(<HInstruction>[input, context], type),
2816 checkedType = type, 2760 checkedType = type,
2817 receiverTypeCheckSelector = null { 2761 receiverTypeCheckSelector = null {
2818 assert(typeExpression.kind != TypeKind.TYPEDEF); 2762 assert(typeExpression.kind != TypeKind.TYPEDEF);
2819 sourceElement = input.sourceElement; 2763 sourceElement = input.sourceElement;
2820 } 2764 }
2821 2765
2822 bool get hasTypeRepresentation { 2766 bool get hasTypeRepresentation {
2823 return typeExpression.isInterfaceType && inputs.length > 1; 2767 return typeExpression.isInterfaceType && inputs.length > 1;
2824 } 2768 }
2769
2825 HInstruction get typeRepresentation => inputs[1]; 2770 HInstruction get typeRepresentation => inputs[1];
2826 2771
2827 bool get hasContext { 2772 bool get hasContext {
2828 return typeExpression.isFunctionType && inputs.length > 1; 2773 return typeExpression.isFunctionType && inputs.length > 1;
2829 } 2774 }
2775
2830 HInstruction get context => inputs[1]; 2776 HInstruction get context => inputs[1];
2831 2777
2832 HInstruction convertType(Compiler compiler, DartType type, int kind) { 2778 HInstruction convertType(Compiler compiler, DartType type, int kind) {
2833 if (typeExpression == type) { 2779 if (typeExpression == type) {
2834 // Don't omit a boolean conversion (which doesn't allow `null`) unless 2780 // Don't omit a boolean conversion (which doesn't allow `null`) unless
2835 // this type conversion is already a boolean conversion. 2781 // this type conversion is already a boolean conversion.
2836 if (kind != BOOLEAN_CONVERSION_CHECK || 2782 if (kind != BOOLEAN_CONVERSION_CHECK || isBooleanConversionCheck) {
2837 isBooleanConversionCheck) {
2838 return this; 2783 return this;
2839 } 2784 }
2840 } 2785 }
2841 return super.convertType(compiler, type, kind); 2786 return super.convertType(compiler, type, kind);
2842 } 2787 }
2843 2788
2844 bool get isCheckedModeCheck { 2789 bool get isCheckedModeCheck {
2845 return kind == CHECKED_MODE_CHECK 2790 return kind == CHECKED_MODE_CHECK || kind == BOOLEAN_CONVERSION_CHECK;
2846 || kind == BOOLEAN_CONVERSION_CHECK;
2847 } 2791 }
2792
2848 bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK; 2793 bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
2849 bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK; 2794 bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;
2850 bool get isCastTypeCheck => kind == CAST_TYPE_CHECK; 2795 bool get isCastTypeCheck => kind == CAST_TYPE_CHECK;
2851 bool get isBooleanConversionCheck => kind == BOOLEAN_CONVERSION_CHECK; 2796 bool get isBooleanConversionCheck => kind == BOOLEAN_CONVERSION_CHECK;
2852 2797
2853 accept(HVisitor visitor) => visitor.visitTypeConversion(this); 2798 accept(HVisitor visitor) => visitor.visitTypeConversion(this);
2854 2799
2855 bool isJsStatement() => isControlFlow(); 2800 bool isJsStatement() => isControlFlow();
2856 bool isControlFlow() => isArgumentTypeCheck || isReceiverTypeCheck; 2801 bool isControlFlow() => isArgumentTypeCheck || isReceiverTypeCheck;
2857 2802
2858 int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE; 2803 int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
2859 bool typeEquals(HInstruction other) => other is HTypeConversion; 2804 bool typeEquals(HInstruction other) => other is HTypeConversion;
2860 bool isCodeMotionInvariant() => false; 2805 bool isCodeMotionInvariant() => false;
2861 2806
2862 bool dataEquals(HTypeConversion other) { 2807 bool dataEquals(HTypeConversion other) {
2863 return kind == other.kind 2808 return kind == other.kind &&
2864 && typeExpression == other.typeExpression 2809 typeExpression == other.typeExpression &&
2865 && checkedType == other.checkedType 2810 checkedType == other.checkedType &&
2866 && receiverTypeCheckSelector == other.receiverTypeCheckSelector; 2811 receiverTypeCheckSelector == other.receiverTypeCheckSelector;
2867 } 2812 }
2868 } 2813 }
2869 2814
2870 /// The [HTypeKnown] instruction marks a value with a refined type. 2815 /// The [HTypeKnown] instruction marks a value with a refined type.
2871 class HTypeKnown extends HCheck { 2816 class HTypeKnown extends HCheck {
2872 TypeMask knownType; 2817 TypeMask knownType;
2873 bool _isMovable; 2818 bool _isMovable;
2874 2819
2875 HTypeKnown.pinned(TypeMask knownType, HInstruction input) 2820 HTypeKnown.pinned(TypeMask knownType, HInstruction input)
2876 : this.knownType = knownType, 2821 : this.knownType = knownType,
2877 this._isMovable = false, 2822 this._isMovable = false,
2878 super(<HInstruction>[input], knownType); 2823 super(<HInstruction>[input], knownType);
2879 2824
2880 HTypeKnown.witnessed(TypeMask knownType, HInstruction input, 2825 HTypeKnown.witnessed(
2881 HInstruction witness) 2826 TypeMask knownType, HInstruction input, HInstruction witness)
2882 : this.knownType = knownType, 2827 : this.knownType = knownType,
2883 this._isMovable = true, 2828 this._isMovable = true,
2884 super(<HInstruction>[input, witness], knownType); 2829 super(<HInstruction>[input, witness], knownType);
2885 2830
2886 toString() => 'TypeKnown $knownType'; 2831 toString() => 'TypeKnown $knownType';
2887 accept(HVisitor visitor) => visitor.visitTypeKnown(this); 2832 accept(HVisitor visitor) => visitor.visitTypeKnown(this);
2888 2833
2889 bool isJsStatement() => false; 2834 bool isJsStatement() => false;
2890 bool isControlFlow() => false; 2835 bool isControlFlow() => false;
2891 bool canThrow() => false; 2836 bool canThrow() => false;
2892 2837
2893 HInstruction get witness => inputs.length == 2 ? inputs[1] : null; 2838 HInstruction get witness => inputs.length == 2 ? inputs[1] : null;
2894 2839
2895 int typeCode() => HInstruction.TYPE_KNOWN_TYPECODE; 2840 int typeCode() => HInstruction.TYPE_KNOWN_TYPECODE;
2896 bool typeEquals(HInstruction other) => other is HTypeKnown; 2841 bool typeEquals(HInstruction other) => other is HTypeKnown;
2897 bool isCodeMotionInvariant() => true; 2842 bool isCodeMotionInvariant() => true;
2898 bool get isMovable => _isMovable && useGvn(); 2843 bool get isMovable => _isMovable && useGvn();
2899 2844
2900 bool dataEquals(HTypeKnown other) { 2845 bool dataEquals(HTypeKnown other) {
2901 return knownType == other.knownType 2846 return knownType == other.knownType &&
2902 && instructionType == other.instructionType; 2847 instructionType == other.instructionType;
2903 } 2848 }
2904 } 2849 }
2905 2850
2906 class HRangeConversion extends HCheck { 2851 class HRangeConversion extends HCheck {
2907 HRangeConversion(HInstruction input, type) 2852 HRangeConversion(HInstruction input, type)
2908 : super(<HInstruction>[input], type) { 2853 : super(<HInstruction>[input], type) {
2909 sourceElement = input.sourceElement; 2854 sourceElement = input.sourceElement;
2910 } 2855 }
2911 2856
2912 bool get isMovable => false; 2857 bool get isMovable => false;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2979 } else if (parentHeader != null) { 2924 } else if (parentHeader != null) {
2980 workQueue.add(parentHeader); 2925 workQueue.add(parentHeader);
2981 } else { 2926 } else {
2982 block.parentLoopHeader = header; 2927 block.parentLoopHeader = header;
2983 blocks.add(block); 2928 blocks.add(block);
2984 workQueue.addAll(block.predecessors); 2929 workQueue.addAll(block.predecessors);
2985 } 2930 }
2986 } 2931 }
2987 } 2932 }
2988 2933
2989
2990 /** 2934 /**
2991 * Embedding of a [HBlockInformation] for block-structure based traversal 2935 * Embedding of a [HBlockInformation] for block-structure based traversal
2992 * in a dominator based flow traversal by attaching it to a basic block. 2936 * in a dominator based flow traversal by attaching it to a basic block.
2993 * To go back to dominator-based traversal, a [HSubGraphBlockInformation] 2937 * To go back to dominator-based traversal, a [HSubGraphBlockInformation]
2994 * structure can be added in the block structure. 2938 * structure can be added in the block structure.
2995 */ 2939 */
2996 class HBlockFlow { 2940 class HBlockFlow {
2997 final HBlockInformation body; 2941 final HBlockInformation body;
2998 final HBasicBlock continuation; 2942 final HBasicBlock continuation;
2999 HBlockFlow(this.body, this.continuation); 2943 HBlockFlow(this.body, this.continuation);
3000 } 2944 }
3001 2945
3002
3003 /** 2946 /**
3004 * Information about a syntactic-like structure. 2947 * Information about a syntactic-like structure.
3005 */ 2948 */
3006 abstract class HBlockInformation { 2949 abstract class HBlockInformation {
3007 HBasicBlock get start; 2950 HBasicBlock get start;
3008 HBasicBlock get end; 2951 HBasicBlock get end;
3009 bool accept(HBlockInformationVisitor visitor); 2952 bool accept(HBlockInformationVisitor visitor);
3010 } 2953 }
3011 2954
3012
3013 /** 2955 /**
3014 * Information about a statement-like structure. 2956 * Information about a statement-like structure.
3015 */ 2957 */
3016 abstract class HStatementInformation extends HBlockInformation { 2958 abstract class HStatementInformation extends HBlockInformation {
3017 bool accept(HStatementInformationVisitor visitor); 2959 bool accept(HStatementInformationVisitor visitor);
3018 } 2960 }
3019 2961
3020
3021 /** 2962 /**
3022 * Information about an expression-like structure. 2963 * Information about an expression-like structure.
3023 */ 2964 */
3024 abstract class HExpressionInformation extends HBlockInformation { 2965 abstract class HExpressionInformation extends HBlockInformation {
3025 bool accept(HExpressionInformationVisitor visitor); 2966 bool accept(HExpressionInformationVisitor visitor);
3026 HInstruction get conditionExpression; 2967 HInstruction get conditionExpression;
3027 } 2968 }
3028 2969
3029
3030 abstract class HStatementInformationVisitor { 2970 abstract class HStatementInformationVisitor {
3031 bool visitLabeledBlockInfo(HLabeledBlockInformation info); 2971 bool visitLabeledBlockInfo(HLabeledBlockInformation info);
3032 bool visitLoopInfo(HLoopBlockInformation info); 2972 bool visitLoopInfo(HLoopBlockInformation info);
3033 bool visitIfInfo(HIfBlockInformation info); 2973 bool visitIfInfo(HIfBlockInformation info);
3034 bool visitTryInfo(HTryBlockInformation info); 2974 bool visitTryInfo(HTryBlockInformation info);
3035 bool visitSwitchInfo(HSwitchBlockInformation info); 2975 bool visitSwitchInfo(HSwitchBlockInformation info);
3036 bool visitSequenceInfo(HStatementSequenceInformation info); 2976 bool visitSequenceInfo(HStatementSequenceInformation info);
3037 // Pseudo-structure embedding a dominator-based traversal into 2977 // Pseudo-structure embedding a dominator-based traversal into
3038 // the block-structure traversal. This will eventually go away. 2978 // the block-structure traversal. This will eventually go away.
3039 bool visitSubGraphInfo(HSubGraphBlockInformation info); 2979 bool visitSubGraphInfo(HSubGraphBlockInformation info);
3040 } 2980 }
3041 2981
3042
3043 abstract class HExpressionInformationVisitor { 2982 abstract class HExpressionInformationVisitor {
3044 bool visitAndOrInfo(HAndOrBlockInformation info); 2983 bool visitAndOrInfo(HAndOrBlockInformation info);
3045 bool visitSubExpressionInfo(HSubExpressionBlockInformation info); 2984 bool visitSubExpressionInfo(HSubExpressionBlockInformation info);
3046 } 2985 }
3047 2986
3048
3049 abstract class HBlockInformationVisitor 2987 abstract class HBlockInformationVisitor
3050 implements HStatementInformationVisitor, HExpressionInformationVisitor { 2988 implements HStatementInformationVisitor, HExpressionInformationVisitor {}
3051 }
3052
3053 2989
3054 /** 2990 /**
3055 * Generic class wrapping a [SubGraph] as a block-information until 2991 * Generic class wrapping a [SubGraph] as a block-information until
3056 * all structures are handled properly. 2992 * all structures are handled properly.
3057 */ 2993 */
3058 class HSubGraphBlockInformation implements HStatementInformation { 2994 class HSubGraphBlockInformation implements HStatementInformation {
3059 final SubGraph subGraph; 2995 final SubGraph subGraph;
3060 HSubGraphBlockInformation(this.subGraph); 2996 HSubGraphBlockInformation(this.subGraph);
3061 2997
3062 HBasicBlock get start => subGraph.start; 2998 HBasicBlock get start => subGraph.start;
3063 HBasicBlock get end => subGraph.end; 2999 HBasicBlock get end => subGraph.end;
3064 3000
3065 bool accept(HStatementInformationVisitor visitor) => 3001 bool accept(HStatementInformationVisitor visitor) =>
3066 visitor.visitSubGraphInfo(this); 3002 visitor.visitSubGraphInfo(this);
3067 } 3003 }
3068 3004
3069 /** 3005 /**
3070 * Generic class wrapping a [SubExpression] as a block-information until 3006 * Generic class wrapping a [SubExpression] as a block-information until
3071 * expressions structures are handled properly. 3007 * expressions structures are handled properly.
3072 */ 3008 */
3073 class HSubExpressionBlockInformation implements HExpressionInformation { 3009 class HSubExpressionBlockInformation implements HExpressionInformation {
3074 final SubExpression subExpression; 3010 final SubExpression subExpression;
3075 HSubExpressionBlockInformation(this.subExpression); 3011 HSubExpressionBlockInformation(this.subExpression);
3076 3012
3077 HBasicBlock get start => subExpression.start; 3013 HBasicBlock get start => subExpression.start;
3078 HBasicBlock get end => subExpression.end; 3014 HBasicBlock get end => subExpression.end;
3079 3015
3080 HInstruction get conditionExpression => subExpression.conditionExpression; 3016 HInstruction get conditionExpression => subExpression.conditionExpression;
3081 3017
3082 bool accept(HExpressionInformationVisitor visitor) => 3018 bool accept(HExpressionInformationVisitor visitor) =>
3083 visitor.visitSubExpressionInfo(this); 3019 visitor.visitSubExpressionInfo(this);
3084 } 3020 }
3085 3021
3086 /** A sequence of separate statements. */ 3022 /** A sequence of separate statements. */
3087 class HStatementSequenceInformation implements HStatementInformation { 3023 class HStatementSequenceInformation implements HStatementInformation {
3088 final List<HStatementInformation> statements; 3024 final List<HStatementInformation> statements;
3089 HStatementSequenceInformation(this.statements); 3025 HStatementSequenceInformation(this.statements);
3090 3026
3091 HBasicBlock get start => statements[0].start; 3027 HBasicBlock get start => statements[0].start;
3092 HBasicBlock get end => statements.last.end; 3028 HBasicBlock get end => statements.last.end;
3093 3029
3094 bool accept(HStatementInformationVisitor visitor) => 3030 bool accept(HStatementInformationVisitor visitor) =>
3095 visitor.visitSequenceInfo(this); 3031 visitor.visitSequenceInfo(this);
3096 } 3032 }
3097 3033
3098 class HLabeledBlockInformation implements HStatementInformation { 3034 class HLabeledBlockInformation implements HStatementInformation {
3099 final HStatementInformation body; 3035 final HStatementInformation body;
3100 final List<LabelDefinition> labels; 3036 final List<LabelDefinition> labels;
3101 final JumpTarget target; 3037 final JumpTarget target;
3102 final bool isContinue; 3038 final bool isContinue;
3103 3039
3104 HLabeledBlockInformation(this.body, 3040 HLabeledBlockInformation(this.body, List<LabelDefinition> labels,
3105 List<LabelDefinition> labels, 3041 {this.isContinue: false})
3106 {this.isContinue: false}) : 3042 : this.labels = labels,
3107 this.labels = labels, this.target = labels[0].target; 3043 this.target = labels[0].target;
3108 3044
3109 HLabeledBlockInformation.implicit(this.body, 3045 HLabeledBlockInformation.implicit(this.body, this.target,
3110 this.target, 3046 {this.isContinue: false})
3111 {this.isContinue: false}) 3047 : this.labels = const <LabelDefinition>[];
3112 : this.labels = const<LabelDefinition>[];
3113 3048
3114 HBasicBlock get start => body.start; 3049 HBasicBlock get start => body.start;
3115 HBasicBlock get end => body.end; 3050 HBasicBlock get end => body.end;
3116 3051
3117 bool accept(HStatementInformationVisitor visitor) => 3052 bool accept(HStatementInformationVisitor visitor) =>
3118 visitor.visitLabeledBlockInfo(this); 3053 visitor.visitLabeledBlockInfo(this);
3119 } 3054 }
3120 3055
3121 class HLoopBlockInformation implements HStatementInformation { 3056 class HLoopBlockInformation implements HStatementInformation {
3122 static const int WHILE_LOOP = 0; 3057 static const int WHILE_LOOP = 0;
3123 static const int FOR_LOOP = 1; 3058 static const int FOR_LOOP = 1;
3124 static const int DO_WHILE_LOOP = 2; 3059 static const int DO_WHILE_LOOP = 2;
3125 static const int FOR_IN_LOOP = 3; 3060 static const int FOR_IN_LOOP = 3;
3126 static const int SWITCH_CONTINUE_LOOP = 4; 3061 static const int SWITCH_CONTINUE_LOOP = 4;
3127 static const int NOT_A_LOOP = -1; 3062 static const int NOT_A_LOOP = -1;
3128 3063
3129 final int kind; 3064 final int kind;
3130 final HExpressionInformation initializer; 3065 final HExpressionInformation initializer;
3131 final HExpressionInformation condition; 3066 final HExpressionInformation condition;
3132 final HStatementInformation body; 3067 final HStatementInformation body;
3133 final HExpressionInformation updates; 3068 final HExpressionInformation updates;
3134 final JumpTarget target; 3069 final JumpTarget target;
3135 final List<LabelDefinition> labels; 3070 final List<LabelDefinition> labels;
3136 final SourceInformation sourceInformation; 3071 final SourceInformation sourceInformation;
3137 3072
3138 HLoopBlockInformation(this.kind, 3073 HLoopBlockInformation(this.kind, this.initializer, this.condition, this.body,
3139 this.initializer, 3074 this.updates, this.target, this.labels, this.sourceInformation) {
3140 this.condition,
3141 this.body,
3142 this.updates,
3143 this.target,
3144 this.labels,
3145 this.sourceInformation) {
3146 assert( 3075 assert(
3147 (kind == DO_WHILE_LOOP ? body.start : condition.start).isLoopHeader()); 3076 (kind == DO_WHILE_LOOP ? body.start : condition.start).isLoopHeader());
3148 } 3077 }
3149 3078
3150 HBasicBlock get start { 3079 HBasicBlock get start {
3151 if (initializer != null) return initializer.start; 3080 if (initializer != null) return initializer.start;
3152 if (kind == DO_WHILE_LOOP) { 3081 if (kind == DO_WHILE_LOOP) {
3153 return body.start; 3082 return body.start;
3154 } 3083 }
3155 return condition.start; 3084 return condition.start;
3156 } 3085 }
3157 3086
3158 HBasicBlock get loopHeader { 3087 HBasicBlock get loopHeader {
3159 return kind == DO_WHILE_LOOP ? body.start : condition.start; 3088 return kind == DO_WHILE_LOOP ? body.start : condition.start;
3160 } 3089 }
3161 3090
3162 HBasicBlock get end { 3091 HBasicBlock get end {
3163 if (updates != null) return updates.end; 3092 if (updates != null) return updates.end;
3164 if (kind == DO_WHILE_LOOP && condition != null) { 3093 if (kind == DO_WHILE_LOOP && condition != null) {
3165 return condition.end; 3094 return condition.end;
3166 } 3095 }
3167 return body.end; 3096 return body.end;
3168 } 3097 }
3169 3098
3170 bool accept(HStatementInformationVisitor visitor) => 3099 bool accept(HStatementInformationVisitor visitor) =>
3171 visitor.visitLoopInfo(this); 3100 visitor.visitLoopInfo(this);
3172 } 3101 }
3173 3102
3174 class HIfBlockInformation implements HStatementInformation { 3103 class HIfBlockInformation implements HStatementInformation {
3175 final HExpressionInformation condition; 3104 final HExpressionInformation condition;
3176 final HStatementInformation thenGraph; 3105 final HStatementInformation thenGraph;
3177 final HStatementInformation elseGraph; 3106 final HStatementInformation elseGraph;
3178 HIfBlockInformation(this.condition, 3107 HIfBlockInformation(this.condition, this.thenGraph, this.elseGraph);
3179 this.thenGraph,
3180 this.elseGraph);
3181 3108
3182 HBasicBlock get start => condition.start; 3109 HBasicBlock get start => condition.start;
3183 HBasicBlock get end => elseGraph == null ? thenGraph.end : elseGraph.end; 3110 HBasicBlock get end => elseGraph == null ? thenGraph.end : elseGraph.end;
3184 3111
3185 bool accept(HStatementInformationVisitor visitor) => 3112 bool accept(HStatementInformationVisitor visitor) =>
3186 visitor.visitIfInfo(this); 3113 visitor.visitIfInfo(this);
3187 } 3114 }
3188 3115
3189 class HAndOrBlockInformation implements HExpressionInformation { 3116 class HAndOrBlockInformation implements HExpressionInformation {
3190 final bool isAnd; 3117 final bool isAnd;
3191 final HExpressionInformation left; 3118 final HExpressionInformation left;
3192 final HExpressionInformation right; 3119 final HExpressionInformation right;
3193 HAndOrBlockInformation(this.isAnd, 3120 HAndOrBlockInformation(this.isAnd, this.left, this.right);
3194 this.left,
3195 this.right);
3196 3121
3197 HBasicBlock get start => left.start; 3122 HBasicBlock get start => left.start;
3198 HBasicBlock get end => right.end; 3123 HBasicBlock get end => right.end;
3199 3124
3200 // We don't currently use HAndOrBlockInformation. 3125 // We don't currently use HAndOrBlockInformation.
3201 HInstruction get conditionExpression { 3126 HInstruction get conditionExpression {
3202 return null; 3127 return null;
3203 } 3128 }
3129
3204 bool accept(HExpressionInformationVisitor visitor) => 3130 bool accept(HExpressionInformationVisitor visitor) =>
3205 visitor.visitAndOrInfo(this); 3131 visitor.visitAndOrInfo(this);
3206 } 3132 }
3207 3133
3208 class HTryBlockInformation implements HStatementInformation { 3134 class HTryBlockInformation implements HStatementInformation {
3209 final HStatementInformation body; 3135 final HStatementInformation body;
3210 final HLocalValue catchVariable; 3136 final HLocalValue catchVariable;
3211 final HStatementInformation catchBlock; 3137 final HStatementInformation catchBlock;
3212 final HStatementInformation finallyBlock; 3138 final HStatementInformation finallyBlock;
3213 HTryBlockInformation(this.body, 3139 HTryBlockInformation(
3214 this.catchVariable, 3140 this.body, this.catchVariable, this.catchBlock, this.finallyBlock);
3215 this.catchBlock,
3216 this.finallyBlock);
3217 3141
3218 HBasicBlock get start => body.start; 3142 HBasicBlock get start => body.start;
3219 HBasicBlock get end => 3143 HBasicBlock get end =>
3220 finallyBlock == null ? catchBlock.end : finallyBlock.end; 3144 finallyBlock == null ? catchBlock.end : finallyBlock.end;
3221 3145
3222 bool accept(HStatementInformationVisitor visitor) => 3146 bool accept(HStatementInformationVisitor visitor) =>
3223 visitor.visitTryInfo(this); 3147 visitor.visitTryInfo(this);
3224 } 3148 }
3225 3149
3226 class HSwitchBlockInformation implements HStatementInformation { 3150 class HSwitchBlockInformation implements HStatementInformation {
3227 final HExpressionInformation expression; 3151 final HExpressionInformation expression;
3228 final List<HStatementInformation> statements; 3152 final List<HStatementInformation> statements;
3229 final JumpTarget target; 3153 final JumpTarget target;
3230 final List<LabelDefinition> labels; 3154 final List<LabelDefinition> labels;
3231 3155
3232 HSwitchBlockInformation(this.expression, 3156 HSwitchBlockInformation(
3233 this.statements, 3157 this.expression, this.statements, this.target, this.labels);
3234 this.target,
3235 this.labels);
3236 3158
3237 HBasicBlock get start => expression.start; 3159 HBasicBlock get start => expression.start;
3238 HBasicBlock get end { 3160 HBasicBlock get end {
3239 // We don't create a switch block if there are no cases. 3161 // We don't create a switch block if there are no cases.
3240 assert(!statements.isEmpty); 3162 assert(!statements.isEmpty);
3241 return statements.last.end; 3163 return statements.last.end;
3242 } 3164 }
3243 3165
3244 bool accept(HStatementInformationVisitor visitor) => 3166 bool accept(HStatementInformationVisitor visitor) =>
3245 visitor.visitSwitchInfo(this); 3167 visitor.visitSwitchInfo(this);
3246 } 3168 }
3247 3169
3248 class HReadTypeVariable extends HInstruction { 3170 class HReadTypeVariable extends HInstruction {
3249 /// The type variable being read. 3171 /// The type variable being read.
3250 final TypeVariableType dartType; 3172 final TypeVariableType dartType;
3251 3173
3252 final bool hasReceiver; 3174 final bool hasReceiver;
3253 3175
3254 HReadTypeVariable(this.dartType, 3176 HReadTypeVariable(
3255 HInstruction receiver, 3177 this.dartType, HInstruction receiver, TypeMask instructionType)
3256 TypeMask instructionType)
3257 : hasReceiver = true, 3178 : hasReceiver = true,
3258 super(<HInstruction>[receiver], instructionType) { 3179 super(<HInstruction>[receiver], instructionType) {
3259 setUseGvn(); 3180 setUseGvn();
3260 } 3181 }
3261 3182
3262 HReadTypeVariable.noReceiver(this.dartType, 3183 HReadTypeVariable.noReceiver(
3263 HInstruction typeArgument, 3184 this.dartType, HInstruction typeArgument, TypeMask instructionType)
3264 TypeMask instructionType)
3265 : hasReceiver = false, 3185 : hasReceiver = false,
3266 super(<HInstruction>[typeArgument], instructionType) { 3186 super(<HInstruction>[typeArgument], instructionType) {
3267 setUseGvn(); 3187 setUseGvn();
3268 } 3188 }
3269 3189
3270 accept(HVisitor visitor) => visitor.visitReadTypeVariable(this); 3190 accept(HVisitor visitor) => visitor.visitReadTypeVariable(this);
3271 3191
3272 bool canThrow() => false; 3192 bool canThrow() => false;
3273 3193
3274 int typeCode() => HInstruction.READ_TYPE_VARIABLE_TYPECODE; 3194 int typeCode() => HInstruction.READ_TYPE_VARIABLE_TYPECODE;
3275 bool typeEquals(HInstruction other) => other is HReadTypeVariable; 3195 bool typeEquals(HInstruction other) => other is HReadTypeVariable;
3276 3196
3277 bool dataEquals(HReadTypeVariable other) { 3197 bool dataEquals(HReadTypeVariable other) {
3278 return dartType.element == other.dartType.element 3198 return dartType.element == other.dartType.element &&
3279 && hasReceiver == other.hasReceiver; 3199 hasReceiver == other.hasReceiver;
3280 } 3200 }
3281 } 3201 }
3282 3202
3283 abstract class HRuntimeType extends HInstruction { 3203 abstract class HRuntimeType extends HInstruction {
3284 final DartType dartType; 3204 final DartType dartType;
3285 3205
3286 HRuntimeType(List<HInstruction> inputs, 3206 HRuntimeType(
3287 this.dartType, 3207 List<HInstruction> inputs, this.dartType, TypeMask instructionType)
3288 TypeMask instructionType)
3289 : super(inputs, instructionType) { 3208 : super(inputs, instructionType) {
3290 setUseGvn(); 3209 setUseGvn();
3291 } 3210 }
3292 3211
3293 bool canThrow() => false; 3212 bool canThrow() => false;
3294 3213
3295 int typeCode() { 3214 int typeCode() {
3296 throw 'abstract method'; 3215 throw 'abstract method';
3297 } 3216 }
3298 3217
3299 bool typeEquals(HInstruction other) { 3218 bool typeEquals(HInstruction other) {
3300 throw 'abstract method'; 3219 throw 'abstract method';
3301 } 3220 }
3302 3221
3303 bool dataEquals(HRuntimeType other) { 3222 bool dataEquals(HRuntimeType other) {
3304 return dartType == other.dartType; 3223 return dartType == other.dartType;
3305 } 3224 }
3306 } 3225 }
3307 3226
3308 class HFunctionType extends HRuntimeType { 3227 class HFunctionType extends HRuntimeType {
3309 HFunctionType(List<HInstruction> inputs, 3228 HFunctionType(List<HInstruction> inputs, FunctionType dartType,
3310 FunctionType dartType, 3229 TypeMask instructionType)
3311 TypeMask instructionType)
3312 : super(inputs, dartType, instructionType); 3230 : super(inputs, dartType, instructionType);
3313 3231
3314 accept(HVisitor visitor) => visitor.visitFunctionType(this); 3232 accept(HVisitor visitor) => visitor.visitFunctionType(this);
3315 3233
3316 int typeCode() => HInstruction.FUNCTION_TYPE_TYPECODE; 3234 int typeCode() => HInstruction.FUNCTION_TYPE_TYPECODE;
3317 3235
3318 bool typeEquals(HInstruction other) => other is HFunctionType; 3236 bool typeEquals(HInstruction other) => other is HFunctionType;
3319 } 3237 }
3320 3238
3321 class HVoidType extends HRuntimeType { 3239 class HVoidType extends HRuntimeType {
3322 HVoidType(VoidType dartType, TypeMask instructionType) 3240 HVoidType(VoidType dartType, TypeMask instructionType)
3323 : super(const <HInstruction>[], dartType, instructionType); 3241 : super(const <HInstruction>[], dartType, instructionType);
3324 3242
3325 accept(HVisitor visitor) => visitor.visitVoidType(this); 3243 accept(HVisitor visitor) => visitor.visitVoidType(this);
3326 3244
3327 int typeCode() => HInstruction.VOID_TYPE_TYPECODE; 3245 int typeCode() => HInstruction.VOID_TYPE_TYPECODE;
3328 3246
3329 bool typeEquals(HInstruction other) => other is HVoidType; 3247 bool typeEquals(HInstruction other) => other is HVoidType;
3330 } 3248 }
3331 3249
3332 class HInterfaceType extends HRuntimeType { 3250 class HInterfaceType extends HRuntimeType {
3333 HInterfaceType(List<HInstruction> inputs, 3251 HInterfaceType(List<HInstruction> inputs, InterfaceType dartType,
3334 InterfaceType dartType, 3252 TypeMask instructionType)
3335 TypeMask instructionType)
3336 : super(inputs, dartType, instructionType); 3253 : super(inputs, dartType, instructionType);
3337 3254
3338 accept(HVisitor visitor) => visitor.visitInterfaceType(this); 3255 accept(HVisitor visitor) => visitor.visitInterfaceType(this);
3339 3256
3340 int typeCode() => HInstruction.INTERFACE_TYPE_TYPECODE; 3257 int typeCode() => HInstruction.INTERFACE_TYPE_TYPECODE;
3341 3258
3342 bool typeEquals(HInstruction other) => other is HInterfaceType; 3259 bool typeEquals(HInstruction other) => other is HInterfaceType;
3343 } 3260 }
3344 3261
3345 class HDynamicType extends HRuntimeType { 3262 class HDynamicType extends HRuntimeType {
3346 HDynamicType(DynamicType dartType, TypeMask instructionType) 3263 HDynamicType(DynamicType dartType, TypeMask instructionType)
3347 : super(const <HInstruction>[], dartType, instructionType); 3264 : super(const <HInstruction>[], dartType, instructionType);
3348 3265
3349 accept(HVisitor visitor) => visitor.visitDynamicType(this); 3266 accept(HVisitor visitor) => visitor.visitDynamicType(this);
3350 3267
3351 int typeCode() => HInstruction.DYNAMIC_TYPE_TYPECODE; 3268 int typeCode() => HInstruction.DYNAMIC_TYPE_TYPECODE;
3352 3269
3353 bool typeEquals(HInstruction other) => other is HDynamicType; 3270 bool typeEquals(HInstruction other) => other is HDynamicType;
3354 } 3271 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart ('k') | pkg/compiler/lib/src/ssa/optimize.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698