Chromium Code Reviews| 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 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| (...skipping 1943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1954 | 1954 |
| 1955 void visitFieldSet(HFieldSet instruction) { | 1955 void visitFieldSet(HFieldSet instruction) { |
| 1956 HInstruction receiver = | 1956 HInstruction receiver = |
| 1957 instruction.getDartReceiver(compiler).nonCheck(); | 1957 instruction.getDartReceiver(compiler).nonCheck(); |
| 1958 memorySet.registerFieldValueUpdate( | 1958 memorySet.registerFieldValueUpdate( |
| 1959 instruction.element, receiver, instruction.inputs.last); | 1959 instruction.element, receiver, instruction.inputs.last); |
| 1960 } | 1960 } |
| 1961 | 1961 |
| 1962 void visitForeignNew(HForeignNew instruction) { | 1962 void visitForeignNew(HForeignNew instruction) { |
| 1963 memorySet.registerAllocation(instruction); | 1963 memorySet.registerAllocation(instruction); |
| 1964 int argumentIndex = 0; | 1964 if (shouldTrackInitialValues(instruction)) { |
| 1965 instruction.element.forEachInstanceField((_, Element member) { | 1965 int argumentIndex = 0; |
| 1966 if (compiler.elementHasCompileTimeError(member)) return; | 1966 instruction.element.forEachInstanceField((_, Element member) { |
| 1967 memorySet.registerFieldValue( | 1967 if (compiler.elementHasCompileTimeError(member)) return; |
| 1968 member, instruction, instruction.inputs[argumentIndex++]); | 1968 memorySet.registerFieldValue( |
| 1969 }, includeSuperAndInjectedMembers: true); | 1969 member, instruction, instruction.inputs[argumentIndex++]); |
| 1970 }, includeSuperAndInjectedMembers: true); | |
| 1971 } | |
| 1970 // In case this instruction has as input non-escaping objects, we | 1972 // In case this instruction has as input non-escaping objects, we |
| 1971 // need to mark these objects as escaping. | 1973 // need to mark these objects as escaping. |
| 1972 memorySet.killAffectedBy(instruction); | 1974 memorySet.killAffectedBy(instruction); |
| 1973 } | 1975 } |
| 1974 | 1976 |
| 1977 bool shouldTrackInitialValues(HForeignNew instruction) { | |
| 1978 // Don't track initial field values of an allocation that are | |
| 1979 // unprofitable. We search the chain of single uses in allocations for a | |
| 1980 // limited depth. | |
| 1981 | |
| 1982 const MAX_HEAP_DEPTH = 5; | |
| 1983 | |
| 1984 bool interestingUse(HInstruction instruction, int heapDepth) { | |
| 1985 // Heuristic: if the allocation is too deep in heap it is unlikely we will | |
| 1986 // recover a field by load-elimination. | |
| 1987 // TODO(sra): We can measure this depth by looking at load chains. | |
| 1988 if (heapDepth == MAX_HEAP_DEPTH) return false; | |
| 1989 // There are multiple uses so do the full store analysis. | |
| 1990 if (instruction.usedBy.length != 1) return true; | |
| 1991 HInstruction use = instruction.usedBy.single; | |
| 1992 // When the only use is an allocation, the allocation becomes the only | |
| 1993 // heap alias for the current instruction. | |
| 1994 if (use is HForeignNew) return interestingUse(use, heapDepth + 1); | |
| 1995 if (use is HLiteralList) return interestingUse(use, heapDepth + 1); | |
| 1996 if (use is HInvokeStatic) { | |
| 1997 // Assume the argument escapes. All we do with our initial allocation is | |
| 1998 // have it escape or store it into an object that escapes. | |
| 1999 return false; | |
| 2000 // TODO(sra): Handle more functions. `setRuntimeTypeInfo` does not | |
| 2001 // actually kill it's input, but we don't make use that elsewhere so | |
|
floitsch
2015/09/14 16:08:19
of that
sra1
2015/09/14 23:09:45
Done.
| |
| 2002 // there is not point in checking here. | |
| 2003 } | |
| 2004 if (use is HPhi) { | |
| 2005 // The initial allocation (it's only alias) gets merged out of the model | |
| 2006 // of the heap before load. | |
| 2007 return false; | |
| 2008 } | |
| 2009 return true; | |
| 2010 } | |
| 2011 | |
| 2012 return interestingUse(instruction, 0); | |
| 2013 } | |
| 2014 | |
| 1975 void visitInstruction(HInstruction instruction) { | 2015 void visitInstruction(HInstruction instruction) { |
| 1976 if (instruction.isAllocation) { | 2016 if (instruction.isAllocation) { |
| 1977 memorySet.registerAllocation(instruction); | 2017 memorySet.registerAllocation(instruction); |
| 1978 } | 2018 } |
| 1979 memorySet.killAffectedBy(instruction); | 2019 memorySet.killAffectedBy(instruction); |
| 1980 } | 2020 } |
| 1981 | 2021 |
| 1982 void visitLazyStatic(HLazyStatic instruction) { | 2022 void visitLazyStatic(HLazyStatic instruction) { |
| 1983 handleStaticLoad(instruction.element, instruction); | 2023 handleStaticLoad(instruction.element, instruction); |
| 1984 } | 2024 } |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2312 | 2352 |
| 2313 keyedValues.forEach((receiver, values) { | 2353 keyedValues.forEach((receiver, values) { |
| 2314 result.keyedValues[receiver] = | 2354 result.keyedValues[receiver] = |
| 2315 new Map<HInstruction, HInstruction>.from(values); | 2355 new Map<HInstruction, HInstruction>.from(values); |
| 2316 }); | 2356 }); |
| 2317 | 2357 |
| 2318 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2358 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2319 return result; | 2359 return result; |
| 2320 } | 2360 } |
| 2321 } | 2361 } |
| OLD | NEW |