| 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 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 // the emitter. | 851 // the emitter. |
| 852 List<HInstruction> constructorArguments = <HInstruction>[]; | 852 List<HInstruction> constructorArguments = <HInstruction>[]; |
| 853 ClassElement element = classElement; | 853 ClassElement element = classElement; |
| 854 while (element != null) { | 854 while (element != null) { |
| 855 for (Element member in element.members) { | 855 for (Element member in element.members) { |
| 856 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { | 856 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { |
| 857 HInstruction value; | 857 HInstruction value; |
| 858 if (localsHandler.hasValueForDirectLocal(member)) { | 858 if (localsHandler.hasValueForDirectLocal(member)) { |
| 859 value = localsHandler.readLocal(member); | 859 value = localsHandler.readLocal(member); |
| 860 } else { | 860 } else { |
| 861 Constant fieldValue = | 861 var fieldValue = |
| 862 compiler.constantHandler.compileVariable(member); | 862 compiler.compileTimeConstantHandler.compileVariable(member); |
| 863 value = graph.addConstant(fieldValue); | 863 // TODO(floitsch): this constant should be treated like all |
| 864 // other constants and should be at the top of the graph. |
| 865 value = new HLiteral.internal(fieldValue, HType.UNKNOWN); |
| 866 add(value); |
| 864 } | 867 } |
| 865 constructorArguments.add(value); | 868 constructorArguments.add(value); |
| 866 } | 869 } |
| 867 } | 870 } |
| 868 element = element.superclass; | 871 element = element.superclass; |
| 869 } | 872 } |
| 870 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); | 873 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); |
| 871 add(newObject); | 874 add(newObject); |
| 872 // Generate calls to the constructor bodies. | 875 // Generate calls to the constructor bodies. |
| 873 for (int index = constructors.length - 1; index >= 0; index--) { | 876 for (int index = constructors.length - 1; index >= 0; index--) { |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1306 visit(node.receiver); | 1309 visit(node.receiver); |
| 1307 HNot not = new HNot(popBoolified()); | 1310 HNot not = new HNot(popBoolified()); |
| 1308 push(not); | 1311 push(not); |
| 1309 } | 1312 } |
| 1310 | 1313 |
| 1311 void visitUnary(Send node, Operator op) { | 1314 void visitUnary(Send node, Operator op) { |
| 1312 assert(node.argumentsNode is Prefix); | 1315 assert(node.argumentsNode is Prefix); |
| 1313 visit(node.receiver); | 1316 visit(node.receiver); |
| 1314 assert(op.token.kind !== PLUS_TOKEN); | 1317 assert(op.token.kind !== PLUS_TOKEN); |
| 1315 HInstruction operand = pop(); | 1318 HInstruction operand = pop(); |
| 1316 // See if we can constant-fold right away. This avoids rewrites later on. | |
| 1317 if (operand is HConstant) { | |
| 1318 HConstant typedOperand = operand; | |
| 1319 Constant constant = typedOperand.constant; | |
| 1320 Constant folded = constant.unaryFold(op.source.stringValue); | |
| 1321 if (folded !== null) { | |
| 1322 stack.add(graph.addConstant(folded)); | |
| 1323 return; | |
| 1324 } | |
| 1325 } | |
| 1326 HInstruction target = | 1319 HInstruction target = |
| 1327 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1320 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1328 add(target); | 1321 add(target); |
| 1329 switch (op.source.stringValue) { | 1322 switch (op.source.stringValue) { |
| 1330 case "-": push(new HNegate(target, operand)); break; | 1323 case "-": |
| 1324 // TODO(kasperl): Avoid calling visit(node.receiver) above. |
| 1325 if ((operand is HLiteral) && (operand.value is double)) { |
| 1326 stack.add(graph.addNewLiteralDouble(-operand.value)); |
| 1327 } else if ((operand is HLiteral) && (operand.value is int)) { |
| 1328 stack.add(graph.addNewLiteralInt(-operand.value)); |
| 1329 } else { |
| 1330 push(new HNegate(target, operand)); |
| 1331 } |
| 1332 break; |
| 1331 case "~": push(new HBitNot(target, operand)); break; | 1333 case "~": push(new HBitNot(target, operand)); break; |
| 1332 default: unreachable(); | 1334 default: unreachable(); |
| 1333 } | 1335 } |
| 1334 } | 1336 } |
| 1335 | 1337 |
| 1336 void visitBinary(HInstruction left, Operator op, HInstruction right) { | 1338 void visitBinary(HInstruction left, Operator op, HInstruction right) { |
| 1337 Element element = interceptors.getOperatorInterceptor(op); | 1339 Element element = interceptors.getOperatorInterceptor(op); |
| 1338 assert(element != null); | 1340 assert(element != null); |
| 1339 HInstruction target = new HStatic(element); | 1341 HInstruction target = new HStatic(element); |
| 1340 add(target); | 1342 add(target); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1628 for (int i = 0; i < selector.namedArguments.length; i++) { | 1630 for (int i = 0; i < selector.namedArguments.length; i++) { |
| 1629 SourceString name = selector.namedArguments[i]; | 1631 SourceString name = selector.namedArguments[i]; |
| 1630 if (name == parameter.name) { | 1632 if (name == parameter.name) { |
| 1631 foundIndex = i; | 1633 foundIndex = i; |
| 1632 break; | 1634 break; |
| 1633 } | 1635 } |
| 1634 } | 1636 } |
| 1635 if (foundIndex != -1) { | 1637 if (foundIndex != -1) { |
| 1636 list.add(namedArguments[foundIndex]); | 1638 list.add(namedArguments[foundIndex]); |
| 1637 } else { | 1639 } else { |
| 1638 Constant constant = compiler.compileVariable(parameter); | 1640 // TODO(kasperl): This needs more work. Ideally these |
| 1639 list.add(graph.addConstant(constant)); | 1641 // constants should be treated like any other constant and |
| 1642 // canonicalized by the graph methods. |
| 1643 var constant = compiler.compileVariable(parameter); |
| 1644 push(new HLiteral.internal(constant, HType.UNKNOWN)); |
| 1645 list.add(pop()); |
| 1640 } | 1646 } |
| 1641 } | 1647 } |
| 1642 } | 1648 } |
| 1643 } | 1649 } |
| 1644 | 1650 |
| 1645 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 1651 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 1646 for (; !link.isEmpty(); link = link.tail) { | 1652 for (; !link.isEmpty(); link = link.tail) { |
| 1647 visit(link.head); | 1653 visit(link.head); |
| 1648 list.add(pop()); | 1654 list.add(pop()); |
| 1649 } | 1655 } |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1864 HInstruction index; | 1870 HInstruction index; |
| 1865 bool isCompoundAssignment = op.source.stringValue.endsWith('='); | 1871 bool isCompoundAssignment = op.source.stringValue.endsWith('='); |
| 1866 // Compound assignments are considered as being prefix. | 1872 // Compound assignments are considered as being prefix. |
| 1867 bool isPrefix = !node.isPostfix; | 1873 bool isPrefix = !node.isPostfix; |
| 1868 Element getter = elements[node.selector]; | 1874 Element getter = elements[node.selector]; |
| 1869 if (isCompoundAssignment) { | 1875 if (isCompoundAssignment) { |
| 1870 value = pop(); | 1876 value = pop(); |
| 1871 index = pop(); | 1877 index = pop(); |
| 1872 } else { | 1878 } else { |
| 1873 index = pop(); | 1879 index = pop(); |
| 1874 value = graph.addConstantInt(1); | 1880 value = graph.addNewLiteralInt(1); |
| 1875 } | 1881 } |
| 1876 HStatic indexMethod = new HStatic(interceptors.getIndexInterceptor()); | 1882 HStatic indexMethod = new HStatic(interceptors.getIndexInterceptor()); |
| 1877 add(indexMethod); | 1883 add(indexMethod); |
| 1878 HInstruction left = new HIndex(indexMethod, receiver, index); | 1884 HInstruction left = new HIndex(indexMethod, receiver, index); |
| 1879 add(left); | 1885 add(left); |
| 1880 Element opElement = elements[op]; | 1886 Element opElement = elements[op]; |
| 1881 visitBinary(left, op, value); | 1887 visitBinary(left, op, value); |
| 1882 HInstruction assign = new HIndexAssign( | 1888 HInstruction assign = new HIndexAssign( |
| 1883 target, receiver, index, pop()); | 1889 target, receiver, index, pop()); |
| 1884 add(assign); | 1890 add(assign); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1905 Element element = elements[node]; | 1911 Element element = elements[node]; |
| 1906 bool isCompoundAssignment = !node.arguments.isEmpty(); | 1912 bool isCompoundAssignment = !node.arguments.isEmpty(); |
| 1907 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. | 1913 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. |
| 1908 generateGetter(node, elements[node.selector]); | 1914 generateGetter(node, elements[node.selector]); |
| 1909 HInstruction left = pop(); | 1915 HInstruction left = pop(); |
| 1910 HInstruction right; | 1916 HInstruction right; |
| 1911 if (isCompoundAssignment) { | 1917 if (isCompoundAssignment) { |
| 1912 visit(node.argumentsNode); | 1918 visit(node.argumentsNode); |
| 1913 right = pop(); | 1919 right = pop(); |
| 1914 } else { | 1920 } else { |
| 1915 right = graph.addConstantInt(1); | 1921 right = graph.addNewLiteralInt(1); |
| 1916 } | 1922 } |
| 1917 visitBinary(left, op, right); | 1923 visitBinary(left, op, right); |
| 1918 HInstruction operation = pop(); | 1924 HInstruction operation = pop(); |
| 1919 assert(operation !== null); | 1925 assert(operation !== null); |
| 1920 generateSetter(node, element, operation); | 1926 generateSetter(node, element, operation); |
| 1921 if (!isPrefix) { | 1927 if (!isPrefix) { |
| 1922 pop(); | 1928 pop(); |
| 1923 stack.add(left); | 1929 stack.add(left); |
| 1924 } | 1930 } |
| 1925 } | 1931 } |
| 1926 } | 1932 } |
| 1927 | 1933 |
| 1928 void visitLiteralInt(LiteralInt node) { | 1934 void visitLiteralInt(LiteralInt node) { |
| 1929 stack.add(graph.addConstantInt(node.value)); | 1935 stack.add(graph.addNewLiteralInt(node.value)); |
| 1930 } | 1936 } |
| 1931 | 1937 |
| 1932 void visitLiteralDouble(LiteralDouble node) { | 1938 void visitLiteralDouble(LiteralDouble node) { |
| 1933 stack.add(graph.addConstantDouble(node.value)); | 1939 stack.add(graph.addNewLiteralDouble(node.value)); |
| 1934 } | 1940 } |
| 1935 | 1941 |
| 1936 void visitLiteralBool(LiteralBool node) { | 1942 void visitLiteralBool(LiteralBool node) { |
| 1937 stack.add(graph.addConstantBool(node.value)); | 1943 stack.add(graph.addNewLiteralBool(node.value)); |
| 1938 } | 1944 } |
| 1939 | 1945 |
| 1940 void visitLiteralString(LiteralString node) { | 1946 void visitLiteralString(LiteralString node) { |
| 1941 stack.add(graph.addConstantString(node.dartString)); | 1947 stack.add(graph.addNewLiteralString(node.dartString)); |
| 1942 } | 1948 } |
| 1943 | 1949 |
| 1944 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { | 1950 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { |
| 1945 visitLiteralString(node); | 1951 visitLiteralString(node); |
| 1946 } | 1952 } |
| 1947 | 1953 |
| 1948 void visitLiteralNull(LiteralNull node) { | 1954 void visitLiteralNull(LiteralNull node) { |
| 1949 stack.add(graph.addConstantNull()); | 1955 stack.add(graph.addNewLiteralNull()); |
| 1950 } | 1956 } |
| 1951 | 1957 |
| 1952 visitNodeList(NodeList node) { | 1958 visitNodeList(NodeList node) { |
| 1953 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 1959 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 1954 visit(link.head); | 1960 visit(link.head); |
| 1955 } | 1961 } |
| 1956 } | 1962 } |
| 1957 | 1963 |
| 1958 void visitParenthesizedExpression(ParenthesizedExpression node) { | 1964 void visitParenthesizedExpression(ParenthesizedExpression node) { |
| 1959 visit(node.expression); | 1965 visit(node.expression); |
| 1960 } | 1966 } |
| 1961 | 1967 |
| 1962 visitOperator(Operator node) { | 1968 visitOperator(Operator node) { |
| 1963 // Operators are intercepted in their surrounding Send nodes. | 1969 // Operators are intercepted in their surrounding Send nodes. |
| 1964 unreachable(); | 1970 unreachable(); |
| 1965 } | 1971 } |
| 1966 | 1972 |
| 1967 visitReturn(Return node) { | 1973 visitReturn(Return node) { |
| 1968 HInstruction value; | 1974 HInstruction value; |
| 1969 if (node.expression === null) { | 1975 if (node.expression === null) { |
| 1970 value = graph.addConstantNull(); | 1976 value = graph.addNewLiteralNull(); |
| 1971 } else { | 1977 } else { |
| 1972 visit(node.expression); | 1978 visit(node.expression); |
| 1973 value = pop(); | 1979 value = pop(); |
| 1974 } | 1980 } |
| 1975 close(new HReturn(value)).addSuccessor(graph.exit); | 1981 close(new HReturn(value)).addSuccessor(graph.exit); |
| 1976 } | 1982 } |
| 1977 | 1983 |
| 1978 visitThrow(Throw node) { | 1984 visitThrow(Throw node) { |
| 1979 if (node.expression === null) { | 1985 if (node.expression === null) { |
| 1980 HInstruction exception = rethrowableException; | 1986 HInstruction exception = rethrowableException; |
| 1981 if (exception === null) { | 1987 if (exception === null) { |
| 1982 exception = graph.addConstantNull(); | 1988 exception = graph.addNewLiteralNull(); |
| 1983 compiler.reportError(node, | 1989 compiler.reportError(node, |
| 1984 'throw without expression outside catch block'); | 1990 'throw without expression outside catch block'); |
| 1985 } | 1991 } |
| 1986 close(new HThrow(exception, isRethrow: true)); | 1992 close(new HThrow(exception, isRethrow: true)); |
| 1987 } else { | 1993 } else { |
| 1988 visit(node.expression); | 1994 visit(node.expression); |
| 1989 close(new HThrow(pop())); | 1995 close(new HThrow(pop())); |
| 1990 } | 1996 } |
| 1991 } | 1997 } |
| 1992 | 1998 |
| 1993 visitTypeAnnotation(TypeAnnotation node) { | 1999 visitTypeAnnotation(TypeAnnotation node) { |
| 1994 compiler.internalError('visiting type annotation in SSA builder', | 2000 compiler.internalError('visiting type annotation in SSA builder', |
| 1995 node: node); | 2001 node: node); |
| 1996 } | 2002 } |
| 1997 | 2003 |
| 1998 visitVariableDefinitions(VariableDefinitions node) { | 2004 visitVariableDefinitions(VariableDefinitions node) { |
| 1999 for (Link<Node> link = node.definitions.nodes; | 2005 for (Link<Node> link = node.definitions.nodes; |
| 2000 !link.isEmpty(); | 2006 !link.isEmpty(); |
| 2001 link = link.tail) { | 2007 link = link.tail) { |
| 2002 Node definition = link.head; | 2008 Node definition = link.head; |
| 2003 if (definition is Identifier) { | 2009 if (definition is Identifier) { |
| 2004 HInstruction initialValue = graph.addConstantNull(); | 2010 HInstruction initialValue = graph.addNewLiteralNull(); |
| 2005 localsHandler.updateLocal(elements[definition], initialValue); | 2011 localsHandler.updateLocal(elements[definition], initialValue); |
| 2006 } else { | 2012 } else { |
| 2007 assert(definition is SendSet); | 2013 assert(definition is SendSet); |
| 2008 visitSendSet(definition); | 2014 visitSendSet(definition); |
| 2009 pop(); // Discard value. | 2015 pop(); // Discard value. |
| 2010 } | 2016 } |
| 2011 } | 2017 } |
| 2012 } | 2018 } |
| 2013 | 2019 |
| 2014 visitLiteralList(LiteralList node) { | 2020 visitLiteralList(LiteralList node) { |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2311 new HInvokeStatic(Selector.INVOCATION_1, inputs); | 2317 new HInvokeStatic(Selector.INVOCATION_1, inputs); |
| 2312 add(unwrappedException); | 2318 add(unwrappedException); |
| 2313 | 2319 |
| 2314 tryInstruction.exception = exception; | 2320 tryInstruction.exception = exception; |
| 2315 Link<Node> link = node.catchBlocks.nodes; | 2321 Link<Node> link = node.catchBlocks.nodes; |
| 2316 | 2322 |
| 2317 void pushCondition(CatchBlock catchBlock) { | 2323 void pushCondition(CatchBlock catchBlock) { |
| 2318 VariableDefinitions declaration = catchBlock.formals.nodes.head; | 2324 VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 2319 HInstruction condition = null; | 2325 HInstruction condition = null; |
| 2320 if (declaration.type == null) { | 2326 if (declaration.type == null) { |
| 2321 condition = graph.addConstantBool(true); | 2327 condition = graph.addNewLiteralTrue(); |
| 2322 stack.add(condition); | 2328 stack.add(condition); |
| 2323 } else { | 2329 } else { |
| 2324 Element typeElement = elements[declaration.type]; | 2330 Element typeElement = elements[declaration.type]; |
| 2325 if (typeElement == null) { | 2331 if (typeElement == null) { |
| 2326 compiler.cancel('Catch with unresolved type', node: catchBlock); | 2332 compiler.cancel('Catch with unresolved type', node: catchBlock); |
| 2327 } | 2333 } |
| 2328 condition = new HIs(typeElement, unwrappedException); | 2334 condition = new HIs(typeElement, unwrappedException); |
| 2329 push(condition); | 2335 push(condition); |
| 2330 } | 2336 } |
| 2331 } | 2337 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2381 visitCatchBlock(CatchBlock node) { | 2387 visitCatchBlock(CatchBlock node) { |
| 2382 visit(node.block); | 2388 visit(node.block); |
| 2383 } | 2389 } |
| 2384 | 2390 |
| 2385 visitTypedef(Typedef node) { | 2391 visitTypedef(Typedef node) { |
| 2386 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 2392 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 2387 } | 2393 } |
| 2388 | 2394 |
| 2389 generateUnimplemented(String reason, [bool isExpression = false]) { | 2395 generateUnimplemented(String reason, [bool isExpression = false]) { |
| 2390 DartString string = new DartString.literal(reason); | 2396 DartString string = new DartString.literal(reason); |
| 2391 HInstruction message = graph.addConstantString(string); | 2397 HInstruction message = graph.addNewLiteralString(string); |
| 2392 | 2398 |
| 2393 // Normally, we would call [close] here. However, then we hit | 2399 // Normally, we would call [close] here. However, then we hit |
| 2394 // another unimplemented feature: aborting loop body. Simply | 2400 // another unimplemented feature: aborting loop body. Simply |
| 2395 // calling [add] does not work as it asserts that the instruction | 2401 // calling [add] does not work as it asserts that the instruction |
| 2396 // isn't a control flow instruction. So we inline parts of [add]. | 2402 // isn't a control flow instruction. So we inline parts of [add]. |
| 2397 current.addAfter(current.last, new HThrow(message)); | 2403 current.addAfter(current.last, new HThrow(message)); |
| 2398 if (isExpression) { | 2404 if (isExpression) { |
| 2399 stack.add(graph.addConstantNull()); | 2405 stack.add(graph.addNewLiteralNull()); |
| 2400 } | 2406 } |
| 2401 } | 2407 } |
| 2402 } | 2408 } |
| OLD | NEW |