| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 } else if (kind == ElementKind.FIELD) { | 46 } else if (kind == ElementKind.FIELD) { |
| 47 assert(!element.isInstanceMember()); | 47 assert(!element.isInstanceMember()); |
| 48 graph = builder.buildLazyInitializer(element); | 48 graph = builder.buildLazyInitializer(element); |
| 49 } else { | 49 } else { |
| 50 compiler.internalErrorOnElement(element, | 50 compiler.internalErrorOnElement(element, |
| 51 'unexpected element kind $kind'); | 51 'unexpected element kind $kind'); |
| 52 } | 52 } |
| 53 assert(graph.isValid()); | 53 assert(graph.isValid()); |
| 54 if (!identical(kind, ElementKind.FIELD)) { | 54 if (!identical(kind, ElementKind.FIELD)) { |
| 55 FunctionElement function = element; | 55 FunctionElement function = element; |
| 56 graph.calledInLoop = compiler.world.isCalledInLoop(function); | |
| 57 FunctionSignature signature = function.computeSignature(compiler); | 56 FunctionSignature signature = function.computeSignature(compiler); |
| 58 signature.forEachOptionalParameter((Element parameter) { | 57 signature.forEachOptionalParameter((Element parameter) { |
| 59 // This ensures the default value will be computed. | 58 // This ensures the default value will be computed. |
| 60 builder.compileVariable(parameter); | 59 builder.compileVariable(parameter); |
| 61 }); | 60 }); |
| 62 } | 61 } |
| 63 | 62 |
| 64 if (compiler.tracer.enabled) { | 63 if (compiler.tracer.enabled) { |
| 65 String name; | 64 String name; |
| 66 if (element.isMember()) { | 65 if (element.isMember()) { |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 925 parameters = new Map<Element, HInstruction>(), | 924 parameters = new Map<Element, HInstruction>(), |
| 926 sourceElementStack = <Element>[work.element], | 925 sourceElementStack = <Element>[work.element], |
| 927 inliningStack = <InliningState>[], | 926 inliningStack = <InliningState>[], |
| 928 rti = builder.backend.rti, | 927 rti = builder.backend.rti, |
| 929 super(work.resolutionTree) { | 928 super(work.resolutionTree) { |
| 930 localsHandler = new LocalsHandler(this); | 929 localsHandler = new LocalsHandler(this); |
| 931 } | 930 } |
| 932 | 931 |
| 933 static const MAX_INLINING_DEPTH = 3; | 932 static const MAX_INLINING_DEPTH = 3; |
| 934 static const MAX_INLINING_NODES = 46; | 933 static const MAX_INLINING_NODES = 46; |
| 934 |
| 935 List<InliningState> inliningStack; | 935 List<InliningState> inliningStack; |
| 936 |
| 936 Element returnElement; | 937 Element returnElement; |
| 937 DartType returnType; | 938 DartType returnType; |
| 939 |
| 938 bool inTryStatement = false; | 940 bool inTryStatement = false; |
| 941 int loopNesting = 0; |
| 939 | 942 |
| 940 HBasicBlock get current => _current; | 943 HBasicBlock get current => _current; |
| 941 void set current(c) { | 944 void set current(c) { |
| 942 isReachable = c != null; | 945 isReachable = c != null; |
| 943 _current = c; | 946 _current = c; |
| 944 } | 947 } |
| 945 | 948 |
| 946 /** | 949 /** |
| 947 * Compiles compile-time constants. Never returns [:null:]. If the | 950 * Compiles compile-time constants. Never returns [:null:]. If the |
| 948 * initial value is not a compile-time constants, it reports an | 951 * initial value is not a compile-time constants, it reports an |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 }); | 998 }); |
| 996 } | 999 } |
| 997 | 1000 |
| 998 /** | 1001 /** |
| 999 * Documentation wanted -- johnniwinther | 1002 * Documentation wanted -- johnniwinther |
| 1000 * | 1003 * |
| 1001 * Invariant: [functionElement] must be an implementation element. | 1004 * Invariant: [functionElement] must be an implementation element. |
| 1002 */ | 1005 */ |
| 1003 HGraph buildMethod(FunctionElement functionElement) { | 1006 HGraph buildMethod(FunctionElement functionElement) { |
| 1004 assert(invariant(functionElement, functionElement.isImplementation)); | 1007 assert(invariant(functionElement, functionElement.isImplementation)); |
| 1008 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement); |
| 1005 FunctionExpression function = functionElement.parseNode(compiler); | 1009 FunctionExpression function = functionElement.parseNode(compiler); |
| 1006 assert(function != null); | 1010 assert(function != null); |
| 1007 assert(!function.modifiers.isExternal()); | 1011 assert(!function.modifiers.isExternal()); |
| 1008 assert(elements[function] != null); | 1012 assert(elements[function] != null); |
| 1009 openFunction(functionElement, function); | 1013 openFunction(functionElement, function); |
| 1010 SourceString name = functionElement.name; | 1014 SourceString name = functionElement.name; |
| 1011 // If [functionElement] is `operator==` we explicitely add a null check at | 1015 // If [functionElement] is `operator==` we explicitely add a null check at |
| 1012 // the beginning of the method. This is to avoid having call sites do the | 1016 // the beginning of the method. This is to avoid having call sites do the |
| 1013 // null check. | 1017 // null check. |
| 1014 if (name == const SourceString('==')) { | 1018 if (name == const SourceString('==')) { |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1215 Selector selector, | 1219 Selector selector, |
| 1216 List<HInstruction> providedArguments, | 1220 List<HInstruction> providedArguments, |
| 1217 Node currentNode) { | 1221 Node currentNode) { |
| 1218 backend.registerStaticUse(element, compiler.enqueuer.codegen); | 1222 backend.registerStaticUse(element, compiler.enqueuer.codegen); |
| 1219 // We cannot inline a method from a deferred library into a method | 1223 // We cannot inline a method from a deferred library into a method |
| 1220 // which isn't deferred. | 1224 // which isn't deferred. |
| 1221 // TODO(ahe): But we should still inline into the same | 1225 // TODO(ahe): But we should still inline into the same |
| 1222 // connected-component of the deferred library. | 1226 // connected-component of the deferred library. |
| 1223 if (compiler.deferredLoadTask.isDeferred(element)) return false; | 1227 if (compiler.deferredLoadTask.isDeferred(element)) return false; |
| 1224 if (compiler.disableInlining) return false; | 1228 if (compiler.disableInlining) return false; |
| 1225 if (inliningStack.length > MAX_INLINING_DEPTH) return false; | 1229 |
| 1230 if (loopNesting == 0 && !graph.calledInLoop) return false; |
| 1231 int maxDepth = (loopNesting > 0) ? MAX_INLINING_DEPTH : 1; |
| 1232 if (inliningStack.length >= maxDepth) return false; |
| 1226 | 1233 |
| 1227 // Ensure that [element] is an implementation element. | 1234 // Ensure that [element] is an implementation element. |
| 1228 element = element.implementation; | 1235 element = element.implementation; |
| 1229 FunctionElement function = element; | 1236 FunctionElement function = element; |
| 1230 bool canBeInlined = backend.canBeInlined[function]; | 1237 bool canBeInlined = backend.canBeInlined[function]; |
| 1231 if (canBeInlined == false) return false; | 1238 if (canBeInlined == false) return false; |
| 1232 assert(selector != null | 1239 assert(selector != null |
| 1233 || Elements.isStaticOrTopLevel(element) | 1240 || Elements.isStaticOrTopLevel(element) |
| 1234 || element.isGenerativeConstructorBody()); | 1241 || element.isGenerativeConstructorBody()); |
| 1235 if (selector != null && !selector.applies(function, compiler)) return false; | 1242 if (selector != null && !selector.applies(function, compiler)) return false; |
| (...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 HBasicBlock startBlock; | 2099 HBasicBlock startBlock; |
| 2093 if (initialize != null) { | 2100 if (initialize != null) { |
| 2094 HBasicBlock initializerBlock = openNewBlock(); | 2101 HBasicBlock initializerBlock = openNewBlock(); |
| 2095 startBlock = initializerBlock; | 2102 startBlock = initializerBlock; |
| 2096 initialize(); | 2103 initialize(); |
| 2097 assert(!isAborted()); | 2104 assert(!isAborted()); |
| 2098 initializerGraph = | 2105 initializerGraph = |
| 2099 new SubExpression(initializerBlock, current); | 2106 new SubExpression(initializerBlock, current); |
| 2100 } | 2107 } |
| 2101 | 2108 |
| 2109 loopNesting++; |
| 2102 JumpHandler jumpHandler = beginLoopHeader(loop); | 2110 JumpHandler jumpHandler = beginLoopHeader(loop); |
| 2103 HLoopInformation loopInfo = current.loopInformation; | 2111 HLoopInformation loopInfo = current.loopInformation; |
| 2104 HBasicBlock conditionBlock = current; | 2112 HBasicBlock conditionBlock = current; |
| 2105 if (startBlock == null) startBlock = conditionBlock; | 2113 if (startBlock == null) startBlock = conditionBlock; |
| 2106 | 2114 |
| 2107 HInstruction conditionInstruction = condition(); | 2115 HInstruction conditionInstruction = condition(); |
| 2108 HBasicBlock conditionExitBlock = | 2116 HBasicBlock conditionExitBlock = |
| 2109 close(new HLoopBranch(conditionInstruction)); | 2117 close(new HLoopBranch(conditionInstruction)); |
| 2110 SubExpression conditionExpression = | 2118 SubExpression conditionExpression = |
| 2111 new SubExpression(conditionBlock, conditionExitBlock); | 2119 new SubExpression(conditionBlock, conditionExitBlock); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2251 conditionBlock.setBlockFlow(labelInfo, current); | 2259 conditionBlock.setBlockFlow(labelInfo, current); |
| 2252 | 2260 |
| 2253 jumpHandler.forEachBreak((HBreak breakInstruction, _) { | 2261 jumpHandler.forEachBreak((HBreak breakInstruction, _) { |
| 2254 HBasicBlock block = breakInstruction.block; | 2262 HBasicBlock block = breakInstruction.block; |
| 2255 block.addAtExit(new HBreak.toLabel(label)); | 2263 block.addAtExit(new HBreak.toLabel(label)); |
| 2256 block.remove(breakInstruction); | 2264 block.remove(breakInstruction); |
| 2257 }); | 2265 }); |
| 2258 } | 2266 } |
| 2259 } | 2267 } |
| 2260 jumpHandler.close(); | 2268 jumpHandler.close(); |
| 2269 loopNesting--; |
| 2261 } | 2270 } |
| 2262 | 2271 |
| 2263 visitFor(For node) { | 2272 visitFor(For node) { |
| 2264 assert(isReachable); | 2273 assert(isReachable); |
| 2265 assert(node.body != null); | 2274 assert(node.body != null); |
| 2266 void buildInitializer() { | 2275 void buildInitializer() { |
| 2267 if (node.initializer == null) return; | 2276 if (node.initializer == null) return; |
| 2268 Node initializer = node.initializer; | 2277 Node initializer = node.initializer; |
| 2269 if (initializer != null) { | 2278 if (initializer != null) { |
| 2270 visit(initializer); | 2279 visit(initializer); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2305 () {}, | 2314 () {}, |
| 2306 buildCondition, | 2315 buildCondition, |
| 2307 () {}, | 2316 () {}, |
| 2308 () { visit(node.body); }); | 2317 () { visit(node.body); }); |
| 2309 } | 2318 } |
| 2310 | 2319 |
| 2311 visitDoWhile(DoWhile node) { | 2320 visitDoWhile(DoWhile node) { |
| 2312 assert(isReachable); | 2321 assert(isReachable); |
| 2313 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 2322 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 2314 localsHandler.startLoop(node); | 2323 localsHandler.startLoop(node); |
| 2324 loopNesting++; |
| 2315 JumpHandler jumpHandler = beginLoopHeader(node); | 2325 JumpHandler jumpHandler = beginLoopHeader(node); |
| 2316 HLoopInformation loopInfo = current.loopInformation; | 2326 HLoopInformation loopInfo = current.loopInformation; |
| 2317 HBasicBlock loopEntryBlock = current; | 2327 HBasicBlock loopEntryBlock = current; |
| 2318 HBasicBlock bodyEntryBlock = current; | 2328 HBasicBlock bodyEntryBlock = current; |
| 2319 TargetElement target = elements[node]; | 2329 TargetElement target = elements[node]; |
| 2320 bool hasContinues = target != null && target.isContinueTarget; | 2330 bool hasContinues = target != null && target.isContinueTarget; |
| 2321 if (hasContinues) { | 2331 if (hasContinues) { |
| 2322 // Add extra block to hang labels on. | 2332 // Add extra block to hang labels on. |
| 2323 // It doesn't currently work if they are on the same block as the | 2333 // It doesn't currently work if they are on the same block as the |
| 2324 // HLoopInfo. The handling of HLabeledBlockInformation will visit a | 2334 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2430 new HSubGraphBlockInformation(bodyGraph), <LabelElement>[label]); | 2440 new HSubGraphBlockInformation(bodyGraph), <LabelElement>[label]); |
| 2431 loopEntryBlock.setBlockFlow(info, current); | 2441 loopEntryBlock.setBlockFlow(info, current); |
| 2432 jumpHandler.forEachBreak((HBreak breakInstruction, _) { | 2442 jumpHandler.forEachBreak((HBreak breakInstruction, _) { |
| 2433 HBasicBlock block = breakInstruction.block; | 2443 HBasicBlock block = breakInstruction.block; |
| 2434 block.addAtExit(new HBreak.toLabel(label)); | 2444 block.addAtExit(new HBreak.toLabel(label)); |
| 2435 block.remove(breakInstruction); | 2445 block.remove(breakInstruction); |
| 2436 }); | 2446 }); |
| 2437 } | 2447 } |
| 2438 } | 2448 } |
| 2439 jumpHandler.close(); | 2449 jumpHandler.close(); |
| 2450 loopNesting--; |
| 2440 } | 2451 } |
| 2441 | 2452 |
| 2442 visitFunctionExpression(FunctionExpression node) { | 2453 visitFunctionExpression(FunctionExpression node) { |
| 2443 ClosureClassMap nestedClosureData = | 2454 ClosureClassMap nestedClosureData = |
| 2444 compiler.closureToClassMapper.getMappingForNestedFunction(node); | 2455 compiler.closureToClassMapper.getMappingForNestedFunction(node); |
| 2445 assert(nestedClosureData != null); | 2456 assert(nestedClosureData != null); |
| 2446 assert(nestedClosureData.closureClassElement != null); | 2457 assert(nestedClosureData.closureClassElement != null); |
| 2447 ClassElement closureClassElement = | 2458 ClassElement closureClassElement = |
| 2448 nestedClosureData.closureClassElement; | 2459 nestedClosureData.closureClassElement; |
| 2449 FunctionElement callElement = nestedClosureData.callElement; | 2460 FunctionElement callElement = nestedClosureData.callElement; |
| (...skipping 3065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5515 new HSubGraphBlockInformation(elseBranch.graph)); | 5526 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5516 | 5527 |
| 5517 HBasicBlock conditionStartBlock = conditionBranch.block; | 5528 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5518 conditionStartBlock.setBlockFlow(info, joinBlock); | 5529 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5519 SubGraph conditionGraph = conditionBranch.graph; | 5530 SubGraph conditionGraph = conditionBranch.graph; |
| 5520 HIf branch = conditionGraph.end.last; | 5531 HIf branch = conditionGraph.end.last; |
| 5521 assert(branch is HIf); | 5532 assert(branch is HIf); |
| 5522 branch.blockInformation = conditionStartBlock.blockFlow; | 5533 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5523 } | 5534 } |
| 5524 } | 5535 } |
| OLD | NEW |