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

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

Issue 10911062: Codegen support for the argument definition test. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698