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 class Interceptors { | 5 class Interceptors { |
6 Compiler compiler; | 6 Compiler compiler; |
7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
8 | 8 |
9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
799 | 799 |
800 class SsaBuilder extends ResolvedVisitor implements Visitor { | 800 class SsaBuilder extends ResolvedVisitor implements Visitor { |
801 final SsaBuilderTask builder; | 801 final SsaBuilderTask builder; |
802 final Interceptors interceptors; | 802 final Interceptors interceptors; |
803 final WorkItem work; | 803 final WorkItem work; |
804 bool methodInterceptionEnabled; | 804 bool methodInterceptionEnabled; |
805 HGraph graph; | 805 HGraph graph; |
806 LocalsHandler localsHandler; | 806 LocalsHandler localsHandler; |
807 HInstruction rethrowableException; | 807 HInstruction rethrowableException; |
808 Map<Element, HParameterValue> parameters; | 808 Map<Element, HParameterValue> parameters; |
809 Map<Element, HInstruction> parametersWithSentinel; | |
809 | 810 |
810 Map<TargetElement, JumpHandler> jumpTargets; | 811 Map<TargetElement, JumpHandler> jumpTargets; |
811 | 812 |
812 /** | 813 /** |
813 * Variables stored in the current activation. These variables are | 814 * Variables stored in the current activation. These variables are |
814 * being updated in try/catch blocks, and should be | 815 * being updated in try/catch blocks, and should be |
815 * accessed indirectly through HFieldGet and HFieldSet. | 816 * accessed indirectly through [HLocalGet] and [HLocalSet]. |
816 */ | 817 */ |
817 Map<Element, HLocalValue> activationVariables; | 818 Map<Element, HLocalValue> activationVariables; |
818 | 819 |
819 // We build the Ssa graph by simulating a stack machine. | 820 // We build the Ssa graph by simulating a stack machine. |
820 List<HInstruction> stack; | 821 List<HInstruction> stack; |
821 | 822 |
822 // The current block to add instructions to. Might be null, if we are | 823 // The current block to add instructions to. Might be null, if we are |
823 // visiting dead code. | 824 // visiting dead code. |
824 HBasicBlock current; | 825 HBasicBlock current; |
825 // The most recently opened block. Has the same value as [current] while | 826 // The most recently opened block. Has the same value as [current] while |
826 // the block is open, but unlike [current], it isn't cleared when the current | 827 // the block is open, but unlike [current], it isn't cleared when the current |
827 // block is closed. | 828 // block is closed. |
828 HBasicBlock lastOpenedBlock; | 829 HBasicBlock lastOpenedBlock; |
829 | 830 |
830 LibraryElement get currentLibrary => work.element.getLibrary(); | 831 LibraryElement get currentLibrary => work.element.getLibrary(); |
831 Compiler get compiler => builder.compiler; | 832 Compiler get compiler => builder.compiler; |
832 CodeEmitterTask get emitter => builder.emitter; | 833 CodeEmitterTask get emitter => builder.emitter; |
833 | 834 |
834 SsaBuilder(SsaBuilderTask builder, WorkItem work) | 835 SsaBuilder(SsaBuilderTask builder, WorkItem work) |
835 : this.builder = builder, | 836 : this.builder = builder, |
836 this.work = work, | 837 this.work = work, |
837 interceptors = builder.interceptors, | 838 interceptors = builder.interceptors, |
838 methodInterceptionEnabled = true, | 839 methodInterceptionEnabled = true, |
839 graph = new HGraph(), | 840 graph = new HGraph(), |
840 stack = new List<HInstruction>(), | 841 stack = new List<HInstruction>(), |
841 activationVariables = new Map<Element, HLocalValue>(), | 842 activationVariables = new Map<Element, HLocalValue>(), |
842 jumpTargets = new Map<TargetElement, JumpHandler>(), | 843 jumpTargets = new Map<TargetElement, JumpHandler>(), |
843 parameters = new Map<Element, HParameterValue>(), | 844 parameters = new Map<Element, HParameterValue>(), |
845 parametersWithSentinel = new Map<Element, HInstruction>(), | |
844 inliningStack = <InliningState>[], | 846 inliningStack = <InliningState>[], |
845 super(work.resolutionTree) { | 847 super(work.resolutionTree) { |
846 localsHandler = new LocalsHandler(this); | 848 localsHandler = new LocalsHandler(this); |
847 } | 849 } |
848 | 850 |
849 static const MAX_INLINING_DEPTH = 3; | 851 static const MAX_INLINING_DEPTH = 3; |
850 static const MAX_INLINING_SOURCE_SIZE = 100; | 852 static const MAX_INLINING_SOURCE_SIZE = 100; |
851 List<InliningState> inliningStack; | 853 List<InliningState> inliningStack; |
852 Element returnElement = null; | 854 Element returnElement = null; |
853 | 855 |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1219 // these selectors. Maybe the resolver can do more of the work | 1221 // these selectors. Maybe the resolver can do more of the work |
1220 // for us here? | 1222 // for us here? |
1221 LibraryElement library = body.getLibrary(); | 1223 LibraryElement library = body.getLibrary(); |
1222 Selector selector = new Selector.call(name, library, arity); | 1224 Selector selector = new Selector.call(name, library, arity); |
1223 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); | 1225 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); |
1224 } | 1226 } |
1225 close(new HReturn(newObject)).addSuccessor(graph.exit); | 1227 close(new HReturn(newObject)).addSuccessor(graph.exit); |
1226 return closeFunction(); | 1228 return closeFunction(); |
1227 } | 1229 } |
1228 | 1230 |
1231 void addParameterCheckInstruction(Element element) { | |
1232 // This is the code we emit for a parameter that is being checked | |
1233 // on whether it was given at value at the call site: | |
1234 // | |
1235 // foo([a = 42) { | |
1236 // if (?a) print('parameter passed $a'); | |
1237 // } | |
1238 // | |
1239 // foo([a = 42]) { | |
1240 // var t1 = a === sentinel; | |
1241 // if (t1) a = 42; | |
1242 // if (!t1) print('parameter passed ' + a); | |
1243 // } | |
1244 | |
1245 // Fetch the original default value of [element]; | |
1246 ConstantHandler handler = compiler.constantHandler; | |
1247 Constant constant = handler.compileVariable(element); | |
1248 HConstant defaultValue = constant == null | |
1249 ? graph.addConstantNull() | |
1250 : graph.addConstant(constant); | |
1251 | |
1252 // Emit the equality check with the sentinel. | |
1253 HConstant sentinel = graph.addConstant(SentinelConstant.SENTINEL); | |
1254 Element equalsHelper = interceptors.getTripleEqualsInterceptor(); | |
1255 HInstruction target = new HStatic(equalsHelper); | |
1256 add(target); | |
1257 HInstruction operand = parameters[element]; | |
1258 HInstruction check = new HIdentity(target, sentinel, operand); | |
1259 add(check); | |
1260 | |
1261 // If the check succeeds, we must update the parameter with the | |
1262 // default value. | |
1263 handleIf(element.parseNode(compiler), | |
1264 () => stack.add(check), | |
1265 () => localsHandler.updateLocal(element, defaultValue), | |
1266 null); | |
1267 | |
1268 // Create the instruction that parameter checks will use. | |
1269 check = new HNot(check); | |
1270 add(check); | |
1271 | |
1272 // If the parameter check is also used by closures, | |
1273 // we need to update the closure field holding that check. | |
1274 ClosureClassMap closureData = localsHandler.closureData; | |
1275 Element redirect = closureData.parametersWithSentinel[element]; | |
1276 if (redirect != null) { | |
1277 localsHandler.updateLocal(redirect, check); | |
1278 } | |
1279 // Cache the check so that uses in this method share the same | |
1280 // check instruction. | |
1281 parametersWithSentinel[element] = check; | |
1282 } | |
1283 | |
1229 void openFunction(FunctionElement functionElement, | 1284 void openFunction(FunctionElement functionElement, |
1230 FunctionExpression node) { | 1285 FunctionExpression node) { |
1231 HBasicBlock block = graph.addNewBlock(); | 1286 HBasicBlock block = graph.addNewBlock(); |
1232 open(graph.entry); | 1287 open(graph.entry); |
1233 | 1288 |
1234 localsHandler.startFunction(functionElement, node); | 1289 localsHandler.startFunction(functionElement, node); |
1235 close(new HGoto()).addSuccessor(block); | 1290 close(new HGoto()).addSuccessor(block); |
1236 | 1291 |
1237 open(block); | 1292 open(block); |
1238 | 1293 |
1294 FunctionSignature params = functionElement.computeSignature(compiler); | |
1295 params.forEachParameter((Element element) { | |
1296 if (elements.isParameterChecked(element)) { | |
1297 addParameterCheckInstruction(element); | |
1298 } | |
1299 }); | |
1300 | |
1239 // Put the type checks in the first successor of the entry, | 1301 // Put the type checks in the first successor of the entry, |
1240 // because that is where the type guards will also be inserted. | 1302 // because that is where the type guards will also be inserted. |
1241 // This way we ensure that a type guard will dominate the type | 1303 // This way we ensure that a type guard will dominate the type |
1242 // check. | 1304 // check. |
1243 FunctionSignature params = functionElement.computeSignature(compiler); | |
1244 params.forEachParameter((Element element) { | 1305 params.forEachParameter((Element element) { |
1245 HInstruction newParameter = potentiallyCheckType( | 1306 HInstruction newParameter = potentiallyCheckType( |
1246 localsHandler.directLocals[element], element); | 1307 localsHandler.directLocals[element], element); |
1247 localsHandler.directLocals[element] = newParameter; | 1308 localsHandler.directLocals[element] = newParameter; |
1248 }); | 1309 }); |
1249 | 1310 |
1250 // Add the type parameters of the class as parameters of this | 1311 // Add the type parameters of the class as parameters of this |
1251 // method. | 1312 // method. |
1252 if (functionElement.isFactoryConstructor() | 1313 if (functionElement.isFactoryConstructor() |
1253 || functionElement.isGenerativeConstructor()) { | 1314 || functionElement.isGenerativeConstructor()) { |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1772 | 1833 |
1773 void visitLogicalNot(Send node) { | 1834 void visitLogicalNot(Send node) { |
1774 assert(node.argumentsNode is Prefix); | 1835 assert(node.argumentsNode is Prefix); |
1775 visit(node.receiver); | 1836 visit(node.receiver); |
1776 HNot not = new HNot(popBoolified()); | 1837 HNot not = new HNot(popBoolified()); |
1777 pushWithPosition(not, node); | 1838 pushWithPosition(not, node); |
1778 } | 1839 } |
1779 | 1840 |
1780 void visitUnary(Send node, Operator op) { | 1841 void visitUnary(Send node, Operator op) { |
1781 String value = op.source.stringValue; | 1842 String value = op.source.stringValue; |
1782 if (value === '?') { | 1843 if (value === '?') { |
kasperl
2012/09/04 10:50:08
node.isParameterCheck?
ngeoffray
2012/09/04 10:53:44
Done.
| |
1783 // TODO(ahe): Implement argument definition test. | 1844 Element element = elements[node.receiver]; |
1784 stack.add(graph.addConstantBool(true)); | 1845 // If the parameter we're accessing is from the current |
1846 // function, we can just fetch the cached instruction. | |
1847 HInstruction check = parametersWithSentinel[element]; | |
1848 if (check !== null) { | |
1849 stack.add(check); | |
1850 } else { | |
1851 // The parameter is from an outer function. Lookup the | |
1852 // element in the closure data of the outer function and read | |
1853 // it. | |
1854 assert(element.enclosingElement != work.element); | |
1855 Node node = element.enclosingElement.parseNode(compiler); | |
1856 ClosureClassMap parameterClosureData = | |
1857 compiler.closureToClassMapper.getMappingForNestedFunction(node); | |
1858 Element fieldCheck = | |
1859 parameterClosureData.parametersWithSentinel[element]; | |
1860 stack.add(localsHandler.readLocal(fieldCheck)); | |
1861 } | |
1785 return; | 1862 return; |
1786 } | 1863 } |
1787 assert(node.argumentsNode is Prefix); | 1864 assert(node.argumentsNode is Prefix); |
1788 visit(node.receiver); | 1865 visit(node.receiver); |
1789 assert(op.token.kind !== PLUS_TOKEN); | 1866 assert(op.token.kind !== PLUS_TOKEN); |
1790 HInstruction operand = pop(); | 1867 HInstruction operand = pop(); |
1791 | 1868 |
1792 HInstruction target = | 1869 HInstruction target = |
1793 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1870 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
1794 add(target); | 1871 add(target); |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2158 */ | 2235 */ |
2159 bool addStaticSendArgumentsToList(Selector selector, | 2236 bool addStaticSendArgumentsToList(Selector selector, |
2160 Link<Node> arguments, | 2237 Link<Node> arguments, |
2161 FunctionElement element, | 2238 FunctionElement element, |
2162 List<HInstruction> list) { | 2239 List<HInstruction> list) { |
2163 HInstruction compileArgument(Node argument) { | 2240 HInstruction compileArgument(Node argument) { |
2164 visit(argument); | 2241 visit(argument); |
2165 return pop(); | 2242 return pop(); |
2166 } | 2243 } |
2167 | 2244 |
2168 HInstruction compileConstant(Element constantElement) { | 2245 HInstruction compileConstant(Element parameter) { |
2169 Constant constant = compiler.compileVariable(constantElement); | 2246 Constant constant; |
2247 TreeElements calleeElements = | |
2248 compiler.enqueuer.resolution.getCachedElements(element); | |
2249 if (calleeElements.isParameterChecked(parameter)) { | |
2250 constant = SentinelConstant.SENTINEL; | |
2251 } else { | |
2252 constant = compiler.compileVariable(parameter); | |
2253 } | |
2170 return graph.addConstant(constant); | 2254 return graph.addConstant(constant); |
2171 } | 2255 } |
2172 | 2256 |
2173 return selector.addArgumentsToList(arguments, | 2257 return selector.addArgumentsToList(arguments, |
2174 list, | 2258 list, |
2175 element, | 2259 element, |
2176 compileArgument, | 2260 compileArgument, |
2177 compileConstant, | 2261 compileConstant, |
2178 compiler); | 2262 compiler); |
2179 } | 2263 } |
(...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3662 } | 3746 } |
3663 | 3747 |
3664 void visitFunctionExpression(Node node) { | 3748 void visitFunctionExpression(Node node) { |
3665 tooDifficult = true; | 3749 tooDifficult = true; |
3666 } | 3750 } |
3667 | 3751 |
3668 void visitFunctionDeclaration(Node node) { | 3752 void visitFunctionDeclaration(Node node) { |
3669 tooDifficult = true; | 3753 tooDifficult = true; |
3670 } | 3754 } |
3671 | 3755 |
3672 void visitSend(Node node) { | 3756 void visitSend(Send node) { |
3757 if (node.isParameterCheck) { | |
3758 tooDifficult = true; | |
3759 return; | |
3760 } | |
3673 node.visitChildren(this); | 3761 node.visitChildren(this); |
3674 } | 3762 } |
3675 | 3763 |
3676 visitLoop(Node node) { | 3764 visitLoop(Node node) { |
3677 node.visitChildren(this); | 3765 node.visitChildren(this); |
3678 if (seenReturn) tooDifficult = true; | 3766 if (seenReturn) tooDifficult = true; |
3679 } | 3767 } |
3680 | 3768 |
3681 void visitReturn(Node node) { | 3769 void visitReturn(Node node) { |
3682 if (seenReturn || node.getBeginToken().stringValue === 'native') { | 3770 if (seenReturn || node.getBeginToken().stringValue === 'native') { |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3933 new HSubGraphBlockInformation(elseBranch.graph)); | 4021 new HSubGraphBlockInformation(elseBranch.graph)); |
3934 | 4022 |
3935 HBasicBlock conditionStartBlock = conditionBranch.block; | 4023 HBasicBlock conditionStartBlock = conditionBranch.block; |
3936 conditionStartBlock.setBlockFlow(info, joinBlock); | 4024 conditionStartBlock.setBlockFlow(info, joinBlock); |
3937 SubGraph conditionGraph = conditionBranch.graph; | 4025 SubGraph conditionGraph = conditionBranch.graph; |
3938 HIf branch = conditionGraph.end.last; | 4026 HIf branch = conditionGraph.end.last; |
3939 assert(branch is HIf); | 4027 assert(branch is HIf); |
3940 branch.blockInformation = conditionStartBlock.blockFlow; | 4028 branch.blockInformation = conditionStartBlock.blockFlow; |
3941 } | 4029 } |
3942 } | 4030 } |
OLD | NEW |