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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 12299006: Start tracking all registered elements in one big full function set (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Register fields. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
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 part of ssa; 5 part of ssa;
6 6
7 /** 7 /**
8 * A special element for the extra parameter taken by intercepted 8 * A special element for the extra parameter taken by intercepted
9 * methods. We need to override [Element.computeType] because our 9 * methods. We need to override [Element.computeType] because our
10 * optimizers may look at its declared type. 10 * optimizers may look at its declared type.
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 updateLocal(boxElement, oldBox); 243 updateLocal(boxElement, oldBox);
244 HInstruction oldValue = readLocal(boxedVariable); 244 HInstruction oldValue = readLocal(boxedVariable);
245 updateLocal(boxElement, newBox); 245 updateLocal(boxElement, newBox);
246 updateLocal(boxedVariable, oldValue); 246 updateLocal(boxedVariable, oldValue);
247 } 247 }
248 updateLocal(boxElement, newBox); 248 updateLocal(boxElement, newBox);
249 } 249 }
250 250
251 HType cachedTypeOfThis; 251 HType cachedTypeOfThis;
252 252
253 HType computeTypeOfThis() { 253 HType getTypeOfThis() {
254 Element element = closureData.thisElement; 254 HType result = cachedTypeOfThis;
255 ClassElement cls = element.enclosingElement.getEnclosingClass(); 255 if (result == null) {
256 Compiler compiler = builder.compiler; 256 Element element = closureData.thisElement;
257 DartType type = cls.computeType(compiler); 257 ClassElement cls = element.enclosingElement.getEnclosingClass();
258 if (compiler.world.isUsedAsMixin(cls)) { 258 Compiler compiler = builder.compiler;
259 // If the enclosing class is used as a mixin, [:this:] can be 259 DartType type = cls.computeType(compiler);
260 // of the class that mixins the enclosing class. These two 260 if (compiler.world.isUsedAsMixin(cls)) {
261 // classes do not have a subclass relationship, so, for 261 // If the enclosing class is used as a mixin, [:this:] can be
262 // simplicity, we mark the type as an interface type. 262 // of the class that mixins the enclosing class. These two
263 cachedTypeOfThis = new HType.nonNullSubtype(type, compiler); 263 // classes do not have a subclass relationship, so, for
264 } else { 264 // simplicity, we mark the type as an interface type.
265 cachedTypeOfThis = new HType.nonNullSubclass(type, compiler); 265 result = new HType.nonNullSubtype(type, compiler);
266 } else {
267 result = new HType.nonNullSubclass(type, compiler);
268 }
269 cachedTypeOfThis = result;
266 } 270 }
267 return cachedTypeOfThis; 271 return result;
268 } 272 }
269 273
270 /** 274 /**
271 * Documentation wanted -- johnniwinther 275 * Documentation wanted -- johnniwinther
272 * 276 *
273 * Invariant: [function] must be an implementation element. 277 * Invariant: [function] must be an implementation element.
274 */ 278 */
275 void startFunction(Element element, Expression node) { 279 void startFunction(Element element, Expression node) {
276 assert(invariant(node, element.isImplementation)); 280 assert(invariant(node, element.isImplementation));
277 Compiler compiler = builder.compiler; 281 Compiler compiler = builder.compiler;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 HThis thisInstruction = new HThis(closureData.thisElement); 317 HThis thisInstruction = new HThis(closureData.thisElement);
314 builder.graph.thisInstruction = thisInstruction; 318 builder.graph.thisInstruction = thisInstruction;
315 builder.graph.entry.addAtEntry(thisInstruction); 319 builder.graph.entry.addAtEntry(thisInstruction);
316 updateLocal(closureData.closureElement, thisInstruction); 320 updateLocal(closureData.closureElement, thisInstruction);
317 } else if (element.isInstanceMember() 321 } else if (element.isInstanceMember()
318 || element.isGenerativeConstructor()) { 322 || element.isGenerativeConstructor()) {
319 // Once closures have been mapped to classes their instance members might 323 // Once closures have been mapped to classes their instance members might
320 // not have any thisElement if the closure was created inside a static 324 // not have any thisElement if the closure was created inside a static
321 // context. 325 // context.
322 HThis thisInstruction = new HThis( 326 HThis thisInstruction = new HThis(
323 closureData.thisElement, computeTypeOfThis()); 327 closureData.thisElement, getTypeOfThis());
324 builder.graph.thisInstruction = thisInstruction; 328 builder.graph.thisInstruction = thisInstruction;
325 builder.graph.entry.addAtEntry(thisInstruction); 329 builder.graph.entry.addAtEntry(thisInstruction);
326 directLocals[closureData.thisElement] = thisInstruction; 330 directLocals[closureData.thisElement] = thisInstruction;
327 } 331 }
328 332
329 // If this method is an intercepted method, add the extra 333 // If this method is an intercepted method, add the extra
330 // parameter to it, that is the actual receiver. 334 // parameter to it, that is the actual receiver.
331 ClassElement cls = element.getEnclosingClass(); 335 ClassElement cls = element.getEnclosingClass();
332 if (builder.backend.isInterceptorClass(cls)) { 336 if (builder.backend.isInterceptorClass(cls)) {
333 HType type = HType.UNKNOWN; 337 HType type = HType.UNKNOWN;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 HLocalValue local = getLocal(element); 432 HLocalValue local = getLocal(element);
429 HInstruction variable = new HLocalGet(element, local); 433 HInstruction variable = new HLocalGet(element, local);
430 builder.add(variable); 434 builder.add(variable);
431 return variable; 435 return variable;
432 } 436 }
433 } 437 }
434 438
435 HInstruction readThis() { 439 HInstruction readThis() {
436 HInstruction res = readLocal(closureData.thisElement); 440 HInstruction res = readLocal(closureData.thisElement);
437 if (res.guaranteedType == null) { 441 if (res.guaranteedType == null) {
438 if (cachedTypeOfThis == null) { 442 res.guaranteedType = getTypeOfThis();
439 computeTypeOfThis();
440 }
441 res.guaranteedType = cachedTypeOfThis;
442 } 443 }
443 return res; 444 return res;
444 } 445 }
445 446
446 HLocalValue getLocal(Element element) { 447 HLocalValue getLocal(Element element) {
447 // If the element is a parameter, we already have a 448 // If the element is a parameter, we already have a
448 // HParameterValue for it. We cannot create another one because 449 // HParameterValue for it. We cannot create another one because
449 // it could then have another name than the real parameter. And 450 // it could then have another name than the real parameter. And
450 // the other one would not know it is just a copy of the real 451 // the other one would not know it is just a copy of the real
451 // parameter. 452 // parameter.
(...skipping 1863 matching lines...) Expand 10 before | Expand all | Expand 10 after
2315 return; 2316 return;
2316 default: 2317 default:
2317 compiler.internalError("Unexpected operator $op", node: op); 2318 compiler.internalError("Unexpected operator $op", node: op);
2318 break; 2319 break;
2319 } 2320 }
2320 2321
2321 pushWithPosition( 2322 pushWithPosition(
2322 buildInvokeDynamic(send, selector, left, [right]), 2323 buildInvokeDynamic(send, selector, left, [right]),
2323 op); 2324 op);
2324 if (op.source.stringValue == '!=') { 2325 if (op.source.stringValue == '!=') {
2325 HBoolify bl = new HBoolify(pop()); 2326 pushWithPosition(new HNot(popBoolified()), op);
2326 add(bl);
2327 pushWithPosition(new HNot(bl), op);
2328 } 2327 }
2329 } 2328 }
2330 2329
2331 HInstruction generateInstanceSendReceiver(Send send) { 2330 HInstruction generateInstanceSendReceiver(Send send) {
2332 assert(Elements.isInstanceSend(send, elements)); 2331 assert(Elements.isInstanceSend(send, elements));
2333 if (send.receiver == null) { 2332 if (send.receiver == null) {
2334 return localsHandler.readThis(); 2333 return localsHandler.readThis();
2335 } 2334 }
2336 visit(send.receiver); 2335 visit(send.receiver);
2337 return pop(); 2336 return pop();
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after
2782 compiler); 2781 compiler);
2783 } 2782 }
2784 2783
2785 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { 2784 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) {
2786 for (; !link.isEmpty; link = link.tail) { 2785 for (; !link.isEmpty; link = link.tail) {
2787 visit(link.head); 2786 visit(link.head);
2788 list.add(pop()); 2787 list.add(pop());
2789 } 2788 }
2790 } 2789 }
2791 2790
2792 visitDynamicSend(Send node) { 2791 bool isThisSend(Send send) {
2792 Node receiver = send.receiver;
2793 if (receiver == null) return true;
2794 Identifier identifier = receiver.asIdentifier();
2795 return identifier != null && identifier.isThis();
2796 }
2797
2798 visitDynamicSend(Send node, {bool inline: true}) {
2793 Selector selector = elements.getSelector(node); 2799 Selector selector = elements.getSelector(node);
2794 2800
2795 SourceString dartMethodName; 2801 // TODO(kasperl): It would be much better to try to get the
2796 bool isNotEquals = false; 2802 // guaranteed type of the receiver after we've evaluated it, but
2797 if (node.isIndex && !node.arguments.tail.isEmpty) { 2803 // because of the way inlining currently works that is hard to do
2798 dartMethodName = Elements.constructOperatorName( 2804 // with re-evaluating the receiver.
2799 const SourceString('[]='), false); 2805 if (isThisSend(node)) {
2800 } else if (node.selector.asOperator() != null) { 2806 HType receiverType = localsHandler.getTypeOfThis();
2801 SourceString name = node.selector.asIdentifier().source; 2807 selector = receiverType.refine(selector, compiler);
2802 isNotEquals = identical(name.stringValue, '!=');
2803 dartMethodName = Elements.constructOperatorName(
2804 name, node.argumentsNode is Prefix);
2805 } else {
2806 dartMethodName = node.selector.asIdentifier().source;
2807 } 2808 }
2808 2809
2809 Element element = elements[node]; 2810 Element element = compiler.world.locateSingleElement(selector);
2810 bool isClosureCall = false; 2811 bool isClosureCall = false;
2811 if (element != null && compiler.world.hasNoOverridingMember(element)) { 2812 if (inline && element != null) {
2812 if (tryInlineMethod(element, selector, node.arguments, node)) { 2813 if (tryInlineMethod(element, selector, node.arguments, node)) {
2813 if (element.isGetter()) { 2814 if (element.isGetter()) {
2814 // If the element is a getter, we are doing a closure call 2815 // If the element is a getter, we are doing a closure call
2815 // on what this getter returns. 2816 // on what this getter returns.
2816 assert(selector.isCall()); 2817 assert(selector.isCall());
2817 isClosureCall = true; 2818 isClosureCall = true;
2818 } else { 2819 } else {
2819 return; 2820 return;
2820 } 2821 }
2821 } 2822 }
(...skipping 16 matching lines...) Expand all
2838 2839
2839 HInstruction invoke; 2840 HInstruction invoke;
2840 if (isClosureCall) { 2841 if (isClosureCall) {
2841 Selector closureSelector = new Selector.callClosureFrom(selector); 2842 Selector closureSelector = new Selector.callClosureFrom(selector);
2842 invoke = new HInvokeClosure(closureSelector, inputs); 2843 invoke = new HInvokeClosure(closureSelector, inputs);
2843 } else { 2844 } else {
2844 invoke = buildInvokeDynamic(node, selector, receiver, inputs); 2845 invoke = buildInvokeDynamic(node, selector, receiver, inputs);
2845 } 2846 }
2846 2847
2847 pushWithPosition(invoke, node); 2848 pushWithPosition(invoke, node);
2848
2849 if (isNotEquals) {
2850 HNot not = new HNot(popBoolified());
2851 push(not);
2852 }
2853 } 2849 }
2854 2850
2855 visitClosureSend(Send node) { 2851 visitClosureSend(Send node) {
2856 Selector selector = elements.getSelector(node); 2852 Selector selector = elements.getSelector(node);
2857 assert(node.receiver == null); 2853 assert(node.receiver == null);
2858 Element element = elements[node]; 2854 Element element = elements[node];
2859 HInstruction closureTarget; 2855 HInstruction closureTarget;
2860 if (element == null) { 2856 if (element == null) {
2861 visit(node.selector); 2857 visit(node.selector);
2862 closureTarget = pop(); 2858 closureTarget = pop();
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
3600 add(target); 3596 add(target);
3601 var inputs = <HInstruction>[target, context]; 3597 var inputs = <HInstruction>[target, context];
3602 addDynamicSendArgumentsToList(node, inputs); 3598 addDynamicSendArgumentsToList(node, inputs);
3603 if (!identical(node.assignmentOperator.source.stringValue, '=')) { 3599 if (!identical(node.assignmentOperator.source.stringValue, '=')) {
3604 compiler.unimplemented('complex super assignment', 3600 compiler.unimplemented('complex super assignment',
3605 node: node.assignmentOperator); 3601 node: node.assignmentOperator);
3606 } 3602 }
3607 push(new HInvokeSuper(inputs, isSetter: true)); 3603 push(new HInvokeSuper(inputs, isSetter: true));
3608 } else if (node.isIndex) { 3604 } else if (node.isIndex) {
3609 if (const SourceString("=") == op.source) { 3605 if (const SourceString("=") == op.source) {
3610 visitDynamicSend(node); 3606 // TODO(kasperl): We temporarily disable inlining because the
3607 // code here cannot deal with it yet.
3608 visitDynamicSend(node, inline: false);
3611 HInvokeDynamicMethod method = pop(); 3609 HInvokeDynamicMethod method = pop();
3612 // Push the value. 3610 // Push the value.
3613 stack.add(method.inputs.last); 3611 stack.add(method.inputs.last);
3614 } else { 3612 } else {
3615 visit(node.receiver); 3613 visit(node.receiver);
3616 HInstruction receiver = pop(); 3614 HInstruction receiver = pop();
3617 visit(node.argumentsNode); 3615 visit(node.argumentsNode);
3618 HInstruction value; 3616 HInstruction value;
3619 HInstruction index; 3617 HInstruction index;
3620 // Compound assignments are considered as being prefix. 3618 // Compound assignments are considered as being prefix.
3621 bool isCompoundAssignment = op.source.stringValue.endsWith('='); 3619 bool isCompoundAssignment = op.source.stringValue.endsWith('=');
3622 bool isPrefix = !node.isPostfix; 3620 bool isPrefix = !node.isPostfix;
3623 Element getter = elements[node.selector];
3624 if (isCompoundAssignment) { 3621 if (isCompoundAssignment) {
3625 value = pop(); 3622 value = pop();
3626 index = pop(); 3623 index = pop();
3627 } else { 3624 } else {
3628 index = pop(); 3625 index = pop();
3629 value = graph.addConstantInt(1, constantSystem); 3626 value = graph.addConstantInt(1, constantSystem);
3630 } 3627 }
3631 3628
3632 HInvokeDynamicMethod left = buildInvokeDynamic( 3629 HInvokeDynamicMethod left = buildInvokeDynamic(
3633 node, new Selector.index(), receiver, [index]); 3630 node, new Selector.index(), receiver, [index]);
3634 add(left); 3631 add(left);
3635 visitBinary(left, op, value, node); 3632 visitBinary(left, op, value, node);
3636 value = pop(); 3633 value = pop();
3637 HInvokeDynamicMethod assign = buildInvokeDynamic( 3634 HInvokeDynamicMethod assign = buildInvokeDynamic(
3638 node, new Selector.indexSet(), receiver, [index, value]); 3635 node, new Selector.indexSet(), receiver, [index, value]);
3639 add(assign); 3636 add(assign);
3640 if (isPrefix) { 3637 if (isPrefix) {
3641 stack.add(value); 3638 stack.add(value);
3642 } else { 3639 } else {
3643 stack.add(left); 3640 stack.add(left);
3644 } 3641 }
3645 } 3642 }
3646 } else if (const SourceString("=") == op.source) { 3643 } else if (const SourceString("=") == op.source) {
3647 Element element = elements[node];
3648 Link<Node> link = node.arguments; 3644 Link<Node> link = node.arguments;
3649 assert(!link.isEmpty && link.tail.isEmpty); 3645 assert(!link.isEmpty && link.tail.isEmpty);
3650 visit(link.head); 3646 visit(link.head);
3651 HInstruction value = pop(); 3647 HInstruction value = pop();
3652 generateSetter(node, element, value); 3648 generateSetter(node, element, value);
3653 } else if (identical(op.source.stringValue, "is")) { 3649 } else if (identical(op.source.stringValue, "is")) {
3654 compiler.internalError("is-operator as SendSet", node: op); 3650 compiler.internalError("is-operator as SendSet", node: op);
3655 } else { 3651 } else {
3656 assert(const SourceString("++") == op.source || 3652 assert(const SourceString("++") == op.source ||
3657 const SourceString("--") == op.source || 3653 const SourceString("--") == op.source ||
3658 node.assignmentOperator.source.stringValue.endsWith("=")); 3654 node.assignmentOperator.source.stringValue.endsWith("="));
3659 Element element = elements[node];
3660 bool isCompoundAssignment = !node.arguments.isEmpty; 3655 bool isCompoundAssignment = !node.arguments.isEmpty;
3661 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. 3656 bool isPrefix = !node.isPostfix; // Compound assignments are prefix.
3662 3657
3663 // [receiver] is only used if the node is an instance send. 3658 // [receiver] is only used if the node is an instance send.
3664 HInstruction receiver = null; 3659 HInstruction receiver = null;
3665 Element selectorElement = elements[node];
3666 if (Elements.isInstanceSend(node, elements)) { 3660 if (Elements.isInstanceSend(node, elements)) {
3667 receiver = generateInstanceSendReceiver(node); 3661 receiver = generateInstanceSendReceiver(node);
3668 generateInstanceGetterWithCompiledReceiver(node, receiver); 3662 generateInstanceGetterWithCompiledReceiver(node, receiver);
3669 } else { 3663 } else {
3670 generateGetter(node, elements[node.selector]); 3664 generateGetter(node, elements[node.selector]);
3671 } 3665 }
3672 HInstruction left = pop(); 3666 HInstruction left = pop();
3673 HInstruction right; 3667 HInstruction right;
3674 if (isCompoundAssignment) { 3668 if (isCompoundAssignment) {
3675 visit(node.argumentsNode); 3669 visit(node.argumentsNode);
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
3925 void buildInitializer() { 3919 void buildInitializer() {
3926 SourceString iteratorName = const SourceString("iterator"); 3920 SourceString iteratorName = const SourceString("iterator");
3927 Selector selector = 3921 Selector selector =
3928 new Selector.getter(iteratorName, currentElement.getLibrary()); 3922 new Selector.getter(iteratorName, currentElement.getLibrary());
3929 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); 3923 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector);
3930 visit(node.expression); 3924 visit(node.expression);
3931 HInstruction receiver = pop(); 3925 HInstruction receiver = pop();
3932 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); 3926 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
3933 if (interceptedClasses == null) { 3927 if (interceptedClasses == null) {
3934 iterator = 3928 iterator =
3935 new HInvokeDynamicGetter(selector, null, receiver, hasGetter); 3929 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter);
3936 } else { 3930 } else {
3937 HInterceptor interceptor = 3931 HInterceptor interceptor =
3938 invokeInterceptor(interceptedClasses, receiver, null); 3932 invokeInterceptor(interceptedClasses, receiver, null);
3939 iterator = 3933 iterator =
3940 new HInvokeDynamicGetter(selector, null, interceptor, hasGetter); 3934 new HInvokeDynamicGetter(selector, null, interceptor, !hasGetter);
3941 // Add the receiver as an argument to the getter call on the 3935 // Add the receiver as an argument to the getter call on the
3942 // interceptor. 3936 // interceptor.
3943 iterator.inputs.add(receiver); 3937 iterator.inputs.add(receiver);
3944 } 3938 }
3945 add(iterator); 3939 add(iterator);
3946 } 3940 }
3947 HInstruction buildCondition() { 3941 HInstruction buildCondition() {
3948 SourceString name = const SourceString('moveNext'); 3942 SourceString name = const SourceString('moveNext');
3949 Selector selector = new Selector.call( 3943 Selector selector = new Selector.call(
3950 name, currentElement.getLibrary(), 0); 3944 name, currentElement.getLibrary(), 0);
3951 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector);
3952 push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator])); 3945 push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator]));
3953 return popBoolified(); 3946 return popBoolified();
3954 } 3947 }
3955 void buildBody() { 3948 void buildBody() {
3956 SourceString name = const SourceString('current'); 3949 SourceString name = const SourceString('current');
3957 Selector call = new Selector.getter(name, currentElement.getLibrary()); 3950 Selector call = new Selector.getter(name, currentElement.getLibrary());
3958 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call); 3951 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call);
3959 push(new HInvokeDynamicGetter(call, null, iterator, hasGetter)); 3952 push(new HInvokeDynamicGetter(call, null, iterator, !hasGetter));
3960 3953
3961 Element variable; 3954 Element variable;
3962 if (node.declaredIdentifier.asSend() != null) { 3955 if (node.declaredIdentifier.asSend() != null) {
3963 variable = elements[node.declaredIdentifier]; 3956 variable = elements[node.declaredIdentifier];
3964 } else { 3957 } else {
3965 assert(node.declaredIdentifier.asVariableDefinitions() != null); 3958 assert(node.declaredIdentifier.asVariableDefinitions() != null);
3966 VariableDefinitions variableDefinitions = node.declaredIdentifier; 3959 VariableDefinitions variableDefinitions = node.declaredIdentifier;
3967 variable = elements[variableDefinitions.definitions.nodes.head]; 3960 variable = elements[variableDefinitions.definitions.nodes.head];
3968 } 3961 }
3969 HInstruction oldVariable = pop(); 3962 HInstruction oldVariable = pop();
(...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after
5076 new HSubGraphBlockInformation(elseBranch.graph)); 5069 new HSubGraphBlockInformation(elseBranch.graph));
5077 5070
5078 HBasicBlock conditionStartBlock = conditionBranch.block; 5071 HBasicBlock conditionStartBlock = conditionBranch.block;
5079 conditionStartBlock.setBlockFlow(info, joinBlock); 5072 conditionStartBlock.setBlockFlow(info, joinBlock);
5080 SubGraph conditionGraph = conditionBranch.graph; 5073 SubGraph conditionGraph = conditionBranch.graph;
5081 HIf branch = conditionGraph.end.last; 5074 HIf branch = conditionGraph.end.last;
5082 assert(branch is HIf); 5075 assert(branch is HIf);
5083 branch.blockInformation = conditionStartBlock.blockFlow; 5076 branch.blockInformation = conditionStartBlock.blockFlow;
5084 } 5077 }
5085 } 5078 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698