| 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 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 // the emitter. | 847 // the emitter. |
| 848 List<HInstruction> constructorArguments = <HInstruction>[]; | 848 List<HInstruction> constructorArguments = <HInstruction>[]; |
| 849 ClassElement element = classElement; | 849 ClassElement element = classElement; |
| 850 while (element != null) { | 850 while (element != null) { |
| 851 for (Element member in element.members) { | 851 for (Element member in element.members) { |
| 852 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { | 852 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { |
| 853 HInstruction value; | 853 HInstruction value; |
| 854 if (localsHandler.hasValueForDirectLocal(member)) { | 854 if (localsHandler.hasValueForDirectLocal(member)) { |
| 855 value = localsHandler.readLocal(member); | 855 value = localsHandler.readLocal(member); |
| 856 } else { | 856 } else { |
| 857 var fieldValue = | 857 Constant fieldValue = |
| 858 compiler.compileTimeConstantHandler.compileVariable(member); | 858 compiler.constantHandler.compileVariable(member); |
| 859 // TODO(floitsch): this constant should be treated like all | 859 value = graph.addConstant(fieldValue); |
| 860 // other constants and should be at the top of the graph. | |
| 861 value = new HLiteral.internal(fieldValue, HType.UNKNOWN); | |
| 862 add(value); | |
| 863 } | 860 } |
| 864 constructorArguments.add(value); | 861 constructorArguments.add(value); |
| 865 } | 862 } |
| 866 } | 863 } |
| 867 element = element.superclass; | 864 element = element.superclass; |
| 868 } | 865 } |
| 869 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); | 866 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); |
| 870 add(newObject); | 867 add(newObject); |
| 871 // Generate calls to the constructor bodies. | 868 // Generate calls to the constructor bodies. |
| 872 for (int index = constructors.length - 1; index >= 0; index--) { | 869 for (int index = constructors.length - 1; index >= 0; index--) { |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1293 visit(node.receiver); | 1290 visit(node.receiver); |
| 1294 HNot not = new HNot(popBoolified()); | 1291 HNot not = new HNot(popBoolified()); |
| 1295 push(not); | 1292 push(not); |
| 1296 } | 1293 } |
| 1297 | 1294 |
| 1298 void visitUnary(Send node, Operator op) { | 1295 void visitUnary(Send node, Operator op) { |
| 1299 assert(node.argumentsNode is Prefix); | 1296 assert(node.argumentsNode is Prefix); |
| 1300 visit(node.receiver); | 1297 visit(node.receiver); |
| 1301 assert(op.token.kind !== PLUS_TOKEN); | 1298 assert(op.token.kind !== PLUS_TOKEN); |
| 1302 HInstruction operand = pop(); | 1299 HInstruction operand = pop(); |
| 1300 // See if we can constant-fold right away. This avoids rewrites later on. |
| 1301 if (operand is HConstant) { |
| 1302 HConstant typedOperand = operand; |
| 1303 Constant constant = typedOperand.constant; |
| 1304 Constant folded = constant.unaryFold(op.source.stringValue); |
| 1305 if (folded !== null) { |
| 1306 stack.add(graph.addConstant(folded)); |
| 1307 return; |
| 1308 } |
| 1309 } |
| 1303 HInstruction target = | 1310 HInstruction target = |
| 1304 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); | 1311 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1305 add(target); | 1312 add(target); |
| 1306 switch (op.source.stringValue) { | 1313 switch (op.source.stringValue) { |
| 1307 case "-": | 1314 case "-": push(new HNegate(target, operand)); break; |
| 1308 // TODO(kasperl): Avoid calling visit(node.receiver) above. | |
| 1309 if ((operand is HLiteral) && (operand.value is double)) { | |
| 1310 stack.add(graph.addNewLiteralDouble(-operand.value)); | |
| 1311 } else if ((operand is HLiteral) && (operand.value is int)) { | |
| 1312 stack.add(graph.addNewLiteralInt(-operand.value)); | |
| 1313 } else { | |
| 1314 push(new HNegate(target, operand)); | |
| 1315 } | |
| 1316 break; | |
| 1317 case "~": push(new HBitNot(target, operand)); break; | 1315 case "~": push(new HBitNot(target, operand)); break; |
| 1318 default: unreachable(); | 1316 default: unreachable(); |
| 1319 } | 1317 } |
| 1320 } | 1318 } |
| 1321 | 1319 |
| 1322 void visitBinary(HInstruction left, Operator op, HInstruction right) { | 1320 void visitBinary(HInstruction left, Operator op, HInstruction right) { |
| 1323 Element element = interceptors.getOperatorInterceptor(op); | 1321 Element element = interceptors.getOperatorInterceptor(op); |
| 1324 assert(element != null); | 1322 assert(element != null); |
| 1325 HInstruction target = new HStatic(element); | 1323 HInstruction target = new HStatic(element); |
| 1326 add(target); | 1324 add(target); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1614 for (int i = 0; i < selector.namedArguments.length; i++) { | 1612 for (int i = 0; i < selector.namedArguments.length; i++) { |
| 1615 SourceString name = selector.namedArguments[i]; | 1613 SourceString name = selector.namedArguments[i]; |
| 1616 if (name == parameter.name) { | 1614 if (name == parameter.name) { |
| 1617 foundIndex = i; | 1615 foundIndex = i; |
| 1618 break; | 1616 break; |
| 1619 } | 1617 } |
| 1620 } | 1618 } |
| 1621 if (foundIndex != -1) { | 1619 if (foundIndex != -1) { |
| 1622 list.add(namedArguments[foundIndex]); | 1620 list.add(namedArguments[foundIndex]); |
| 1623 } else { | 1621 } else { |
| 1624 // TODO(kasperl): This needs more work. Ideally these | 1622 Constant constant = compiler.compileVariable(parameter); |
| 1625 // constants should be treated like any other constant and | 1623 list.add(graph.addConstant(constant)); |
| 1626 // canonicalized by the graph methods. | |
| 1627 var constant = compiler.compileVariable(parameter); | |
| 1628 push(new HLiteral.internal(constant, HType.UNKNOWN)); | |
| 1629 list.add(pop()); | |
| 1630 } | 1624 } |
| 1631 } | 1625 } |
| 1632 } | 1626 } |
| 1633 } | 1627 } |
| 1634 | 1628 |
| 1635 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 1629 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 1636 for (; !link.isEmpty(); link = link.tail) { | 1630 for (; !link.isEmpty(); link = link.tail) { |
| 1637 visit(link.head); | 1631 visit(link.head); |
| 1638 list.add(pop()); | 1632 list.add(pop()); |
| 1639 } | 1633 } |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1854 HInstruction index; | 1848 HInstruction index; |
| 1855 bool isCompoundAssignment = op.source.stringValue.endsWith('='); | 1849 bool isCompoundAssignment = op.source.stringValue.endsWith('='); |
| 1856 // Compound assignments are considered as being prefix. | 1850 // Compound assignments are considered as being prefix. |
| 1857 bool isPrefix = !node.isPostfix; | 1851 bool isPrefix = !node.isPostfix; |
| 1858 Element getter = elements[node.selector]; | 1852 Element getter = elements[node.selector]; |
| 1859 if (isCompoundAssignment) { | 1853 if (isCompoundAssignment) { |
| 1860 value = pop(); | 1854 value = pop(); |
| 1861 index = pop(); | 1855 index = pop(); |
| 1862 } else { | 1856 } else { |
| 1863 index = pop(); | 1857 index = pop(); |
| 1864 value = graph.addNewLiteralInt(1); | 1858 value = graph.addConstantInt(1); |
| 1865 } | 1859 } |
| 1866 HStatic indexMethod = new HStatic(interceptors.getIndexInterceptor()); | 1860 HStatic indexMethod = new HStatic(interceptors.getIndexInterceptor()); |
| 1867 add(indexMethod); | 1861 add(indexMethod); |
| 1868 HInstruction left = new HIndex(indexMethod, receiver, index); | 1862 HInstruction left = new HIndex(indexMethod, receiver, index); |
| 1869 add(left); | 1863 add(left); |
| 1870 Element opElement = elements[op]; | 1864 Element opElement = elements[op]; |
| 1871 visitBinary(left, op, value); | 1865 visitBinary(left, op, value); |
| 1872 HInstruction assign = new HIndexAssign( | 1866 HInstruction assign = new HIndexAssign( |
| 1873 target, receiver, index, pop()); | 1867 target, receiver, index, pop()); |
| 1874 add(assign); | 1868 add(assign); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1895 Element element = elements[node]; | 1889 Element element = elements[node]; |
| 1896 bool isCompoundAssignment = !node.arguments.isEmpty(); | 1890 bool isCompoundAssignment = !node.arguments.isEmpty(); |
| 1897 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. | 1891 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. |
| 1898 generateGetter(node, elements[node.selector]); | 1892 generateGetter(node, elements[node.selector]); |
| 1899 HInstruction left = pop(); | 1893 HInstruction left = pop(); |
| 1900 HInstruction right; | 1894 HInstruction right; |
| 1901 if (isCompoundAssignment) { | 1895 if (isCompoundAssignment) { |
| 1902 visit(node.argumentsNode); | 1896 visit(node.argumentsNode); |
| 1903 right = pop(); | 1897 right = pop(); |
| 1904 } else { | 1898 } else { |
| 1905 right = graph.addNewLiteralInt(1); | 1899 right = graph.addConstantInt(1); |
| 1906 } | 1900 } |
| 1907 visitBinary(left, op, right); | 1901 visitBinary(left, op, right); |
| 1908 HInstruction operation = pop(); | 1902 HInstruction operation = pop(); |
| 1909 assert(operation !== null); | 1903 assert(operation !== null); |
| 1910 generateSetter(node, element, operation); | 1904 generateSetter(node, element, operation); |
| 1911 if (!isPrefix) { | 1905 if (!isPrefix) { |
| 1912 pop(); | 1906 pop(); |
| 1913 stack.add(left); | 1907 stack.add(left); |
| 1914 } | 1908 } |
| 1915 } | 1909 } |
| 1916 } | 1910 } |
| 1917 | 1911 |
| 1918 void visitLiteralInt(LiteralInt node) { | 1912 void visitLiteralInt(LiteralInt node) { |
| 1919 stack.add(graph.addNewLiteralInt(node.value)); | 1913 stack.add(graph.addConstantInt(node.value)); |
| 1920 } | 1914 } |
| 1921 | 1915 |
| 1922 void visitLiteralDouble(LiteralDouble node) { | 1916 void visitLiteralDouble(LiteralDouble node) { |
| 1923 stack.add(graph.addNewLiteralDouble(node.value)); | 1917 stack.add(graph.addConstantDouble(node.value)); |
| 1924 } | 1918 } |
| 1925 | 1919 |
| 1926 void visitLiteralBool(LiteralBool node) { | 1920 void visitLiteralBool(LiteralBool node) { |
| 1927 stack.add(graph.addNewLiteralBool(node.value)); | 1921 stack.add(graph.addConstantBool(node.value)); |
| 1928 } | 1922 } |
| 1929 | 1923 |
| 1930 void visitLiteralString(LiteralString node) { | 1924 void visitLiteralString(LiteralString node) { |
| 1931 stack.add(graph.addNewLiteralString(node.dartString)); | 1925 stack.add(graph.addConstantString(node.dartString)); |
| 1932 } | 1926 } |
| 1933 | 1927 |
| 1934 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { | 1928 void visitLiteralStringJuxtaposition(LiteralStringJuxtaposition node) { |
| 1935 visitLiteralString(node); | 1929 visitLiteralString(node); |
| 1936 } | 1930 } |
| 1937 | 1931 |
| 1938 void visitLiteralNull(LiteralNull node) { | 1932 void visitLiteralNull(LiteralNull node) { |
| 1939 stack.add(graph.addNewLiteralNull()); | 1933 stack.add(graph.addConstantNull()); |
| 1940 } | 1934 } |
| 1941 | 1935 |
| 1942 visitNodeList(NodeList node) { | 1936 visitNodeList(NodeList node) { |
| 1943 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { | 1937 for (Link<Node> link = node.nodes; !link.isEmpty(); link = link.tail) { |
| 1944 visit(link.head); | 1938 visit(link.head); |
| 1945 } | 1939 } |
| 1946 } | 1940 } |
| 1947 | 1941 |
| 1948 void visitParenthesizedExpression(ParenthesizedExpression node) { | 1942 void visitParenthesizedExpression(ParenthesizedExpression node) { |
| 1949 visit(node.expression); | 1943 visit(node.expression); |
| 1950 } | 1944 } |
| 1951 | 1945 |
| 1952 visitOperator(Operator node) { | 1946 visitOperator(Operator node) { |
| 1953 // Operators are intercepted in their surrounding Send nodes. | 1947 // Operators are intercepted in their surrounding Send nodes. |
| 1954 unreachable(); | 1948 unreachable(); |
| 1955 } | 1949 } |
| 1956 | 1950 |
| 1957 visitReturn(Return node) { | 1951 visitReturn(Return node) { |
| 1958 HInstruction value; | 1952 HInstruction value; |
| 1959 if (node.expression === null) { | 1953 if (node.expression === null) { |
| 1960 value = graph.addNewLiteralNull(); | 1954 value = graph.addConstantNull(); |
| 1961 } else { | 1955 } else { |
| 1962 visit(node.expression); | 1956 visit(node.expression); |
| 1963 value = pop(); | 1957 value = pop(); |
| 1964 } | 1958 } |
| 1965 close(new HReturn(value)).addSuccessor(graph.exit); | 1959 close(new HReturn(value)).addSuccessor(graph.exit); |
| 1966 } | 1960 } |
| 1967 | 1961 |
| 1968 visitThrow(Throw node) { | 1962 visitThrow(Throw node) { |
| 1969 if (node.expression === null) { | 1963 if (node.expression === null) { |
| 1970 HInstruction exception = rethrowableException; | 1964 HInstruction exception = rethrowableException; |
| 1971 if (exception === null) { | 1965 if (exception === null) { |
| 1972 exception = graph.addNewLiteralNull(); | 1966 exception = graph.addConstantNull(); |
| 1973 compiler.reportError(node, | 1967 compiler.reportError(node, |
| 1974 'throw without expression outside catch block'); | 1968 'throw without expression outside catch block'); |
| 1975 } | 1969 } |
| 1976 close(new HThrow(exception, isRethrow: true)); | 1970 close(new HThrow(exception, isRethrow: true)); |
| 1977 } else { | 1971 } else { |
| 1978 visit(node.expression); | 1972 visit(node.expression); |
| 1979 close(new HThrow(pop())); | 1973 close(new HThrow(pop())); |
| 1980 } | 1974 } |
| 1981 } | 1975 } |
| 1982 | 1976 |
| 1983 visitTypeAnnotation(TypeAnnotation node) { | 1977 visitTypeAnnotation(TypeAnnotation node) { |
| 1984 compiler.internalError('visiting type annotation in SSA builder', | 1978 compiler.internalError('visiting type annotation in SSA builder', |
| 1985 node: node); | 1979 node: node); |
| 1986 } | 1980 } |
| 1987 | 1981 |
| 1988 visitVariableDefinitions(VariableDefinitions node) { | 1982 visitVariableDefinitions(VariableDefinitions node) { |
| 1989 for (Link<Node> link = node.definitions.nodes; | 1983 for (Link<Node> link = node.definitions.nodes; |
| 1990 !link.isEmpty(); | 1984 !link.isEmpty(); |
| 1991 link = link.tail) { | 1985 link = link.tail) { |
| 1992 Node definition = link.head; | 1986 Node definition = link.head; |
| 1993 if (definition is Identifier) { | 1987 if (definition is Identifier) { |
| 1994 HInstruction initialValue = graph.addNewLiteralNull(); | 1988 HInstruction initialValue = graph.addConstantNull(); |
| 1995 localsHandler.updateLocal(elements[definition], initialValue); | 1989 localsHandler.updateLocal(elements[definition], initialValue); |
| 1996 } else { | 1990 } else { |
| 1997 assert(definition is SendSet); | 1991 assert(definition is SendSet); |
| 1998 visitSendSet(definition); | 1992 visitSendSet(definition); |
| 1999 pop(); // Discard value. | 1993 pop(); // Discard value. |
| 2000 } | 1994 } |
| 2001 } | 1995 } |
| 2002 } | 1996 } |
| 2003 | 1997 |
| 2004 visitLiteralList(LiteralList node) { | 1998 visitLiteralList(LiteralList node) { |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2293 new HInvokeStatic(Selector.INVOCATION_1, inputs); | 2287 new HInvokeStatic(Selector.INVOCATION_1, inputs); |
| 2294 add(unwrappedException); | 2288 add(unwrappedException); |
| 2295 | 2289 |
| 2296 tryInstruction.exception = exception; | 2290 tryInstruction.exception = exception; |
| 2297 Link<Node> link = node.catchBlocks.nodes; | 2291 Link<Node> link = node.catchBlocks.nodes; |
| 2298 | 2292 |
| 2299 void pushCondition(CatchBlock catchBlock) { | 2293 void pushCondition(CatchBlock catchBlock) { |
| 2300 VariableDefinitions declaration = catchBlock.formals.nodes.head; | 2294 VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 2301 HInstruction condition = null; | 2295 HInstruction condition = null; |
| 2302 if (declaration.type == null) { | 2296 if (declaration.type == null) { |
| 2303 condition = graph.addNewLiteralTrue(); | 2297 condition = graph.addConstantBool(true); |
| 2304 stack.add(condition); | 2298 stack.add(condition); |
| 2305 } else { | 2299 } else { |
| 2306 Element typeElement = elements[declaration.type]; | 2300 Element typeElement = elements[declaration.type]; |
| 2307 if (typeElement == null) { | 2301 if (typeElement == null) { |
| 2308 compiler.cancel('Catch with unresolved type', node: catchBlock); | 2302 compiler.cancel('Catch with unresolved type', node: catchBlock); |
| 2309 } | 2303 } |
| 2310 condition = new HIs(typeElement, unwrappedException); | 2304 condition = new HIs(typeElement, unwrappedException); |
| 2311 push(condition); | 2305 push(condition); |
| 2312 } | 2306 } |
| 2313 } | 2307 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2363 visitCatchBlock(CatchBlock node) { | 2357 visitCatchBlock(CatchBlock node) { |
| 2364 visit(node.block); | 2358 visit(node.block); |
| 2365 } | 2359 } |
| 2366 | 2360 |
| 2367 visitTypedef(Typedef node) { | 2361 visitTypedef(Typedef node) { |
| 2368 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 2362 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 2369 } | 2363 } |
| 2370 | 2364 |
| 2371 generateUnimplemented(String reason, [bool isExpression = false]) { | 2365 generateUnimplemented(String reason, [bool isExpression = false]) { |
| 2372 DartString string = new DartString.literal(reason); | 2366 DartString string = new DartString.literal(reason); |
| 2373 HInstruction message = graph.addNewLiteralString(string); | 2367 HInstruction message = graph.addConstantString(string); |
| 2374 | 2368 |
| 2375 // Normally, we would call [close] here. However, then we hit | 2369 // Normally, we would call [close] here. However, then we hit |
| 2376 // another unimplemented feature: aborting loop body. Simply | 2370 // another unimplemented feature: aborting loop body. Simply |
| 2377 // calling [add] does not work as it asserts that the instruction | 2371 // calling [add] does not work as it asserts that the instruction |
| 2378 // isn't a control flow instruction. So we inline parts of [add]. | 2372 // isn't a control flow instruction. So we inline parts of [add]. |
| 2379 current.addAfter(current.last, new HThrow(message)); | 2373 current.addAfter(current.last, new HThrow(message)); |
| 2380 if (isExpression) { | 2374 if (isExpression) { |
| 2381 stack.add(graph.addNewLiteralNull()); | 2375 stack.add(graph.addConstantNull()); |
| 2382 } | 2376 } |
| 2383 } | 2377 } |
| 2384 } | 2378 } |
| OLD | NEW |