40 * default policy. The will get trampolines and only be generated when |
40 * default policy. The will get trampolines and only be generated when |
41 * called |
41 * called |
42 */ |
42 */ |
43 LAZY_INITIALIZATION_PHASE(EnumSet.of(INITIALIZED, PARSED)) { |
43 LAZY_INITIALIZATION_PHASE(EnumSet.of(INITIALIZED, PARSED)) { |
44 @Override |
44 @Override |
45 FunctionNode transform(final Compiler compiler, final FunctionNode fn0) { |
45 FunctionNode transform(final Compiler compiler, final FunctionNode fn) { |
46 |
46 |
47 /* |
47 /* |
48 * For lazy compilation, we might be given a node previously marked |
48 * For lazy compilation, we might be given a node previously marked |
49 * as lazy to compile as the outermost function node in the |
49 * as lazy to compile as the outermost function node in the |
50 * compiler. Unmark it so it can be compiled and not cause |
50 * compiler. Unmark it so it can be compiled and not cause |
56 * TODO: in the future specializations from a callsite will be |
56 * TODO: in the future specializations from a callsite will be |
57 * passed here so we can generate a better non-lazy version of a |
57 * passed here so we can generate a better non-lazy version of a |
58 * function from a trampoline |
58 * function from a trampoline |
59 */ |
59 */ |
60 |
60 |
61 final FunctionNode outermostFunctionNode = compiler.getFunctionNode(); |
61 final FunctionNode outermostFunctionNode = fn; |
62 assert outermostFunctionNode == fn0; |
|
63 |
62 |
64 final Set<FunctionNode> neverLazy = new HashSet<>(); |
63 final Set<FunctionNode> neverLazy = new HashSet<>(); |
65 final Set<FunctionNode> lazy = new HashSet<>(); |
64 final Set<FunctionNode> lazy = new HashSet<>(); |
66 |
65 |
67 FunctionNode newFunctionNode = outermostFunctionNode; |
66 FunctionNode newFunctionNode = outermostFunctionNode; |
170 * Attribution Assign symbols and types to all nodes. |
169 * Attribution Assign symbols and types to all nodes. |
171 */ |
170 */ |
172 ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED)) { |
171 ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED)) { |
173 @Override |
172 @Override |
174 FunctionNode transform(final Compiler compiler, final FunctionNode fn) { |
173 FunctionNode transform(final Compiler compiler, final FunctionNode fn) { |
175 return (FunctionNode)initReturnTypes(fn).accept(new Attr()); |
174 return (FunctionNode)enterAttr(fn).accept(new Attr()); |
176 } |
175 } |
177 |
176 |
178 /** |
177 /** |
179 * Pessimistically set all lazy functions' return types to Object |
178 * Pessimistically set all lazy functions' return types to Object |
|
179 * and the function symbols to object |
180 * @param functionNode node where to start iterating |
180 * @param functionNode node where to start iterating |
181 */ |
181 */ |
182 private FunctionNode initReturnTypes(final FunctionNode functionNode) { |
182 private FunctionNode enterAttr(final FunctionNode functionNode) { |
183 return (FunctionNode)functionNode.accept(new NodeVisitor() { |
183 return (FunctionNode)functionNode.accept(new NodeVisitor() { |
184 @Override |
184 @Override |
185 public Node leaveFunctionNode(final FunctionNode node) { |
185 public Node leaveFunctionNode(final FunctionNode node) { |
186 return node.isLazy() ? |
186 final LexicalContext lc = getLexicalContext(); |
187 node.setReturnType(getLexicalContext(), Type.OBJECT) : |
187 if (node.isLazy()) { |
188 node.setReturnType(getLexicalContext(), Type.UNKNOWN); |
188 FunctionNode newNode = node.setReturnType(getLexicalContext(), Type.OBJECT); |
|
189 return Attr.ensureSymbol(lc, lc.getCurrentBlock(), Type.OBJECT, newNode); |
|
190 } |
|
191 //node may have a reference here that needs to be nulled if it was referred to by |
|
192 //its outer context, if it is lazy and not attributed |
|
193 return node.setReturnType(lc, Type.UNKNOWN).setSymbol(lc, null); |
189 } |
194 } |
190 }); |
195 }); |
191 } |
196 } |
192 |
197 |
193 @Override |
198 @Override |
205 SPLITTING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) { |
210 SPLITTING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) { |
206 @Override |
211 @Override |
207 FunctionNode transform(final Compiler compiler, final FunctionNode fn) { |
212 FunctionNode transform(final Compiler compiler, final FunctionNode fn) { |
208 final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName()); |
213 final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName()); |
209 |
214 |
|
215 // assert fn.isProgram() ; |
210 final FunctionNode newFunctionNode = new Splitter(compiler, fn, outermostCompileUnit).split(fn); |
216 final FunctionNode newFunctionNode = new Splitter(compiler, fn, outermostCompileUnit).split(fn); |
211 |
217 |
212 assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit; |
218 assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit; |
213 |
219 |
214 if (newFunctionNode.isStrict()) { |
220 if (newFunctionNode.isStrict()) { |
215 assert compiler.getStrictMode(); |
221 assert compiler.getStrictMode(); |
216 compiler.setStrictMode(true); |
222 compiler.setStrictMode(true); |
217 } |
223 } |
218 |
|
219 /* |
|
220 newFunctionNode.accept(new NodeVisitor() { |
|
221 @Override |
|
222 public boolean enterFunctionNode(final FunctionNode functionNode) { |
|
223 assert functionNode.getCompileUnit() != null : functionNode.getName() + " " + Debug.id(functionNode) + " has no compile unit"; |
|
224 return true; |
|
225 } |
|
226 });*/ |
|
227 |
224 |
228 return newFunctionNode; |
225 return newFunctionNode; |
229 } |
226 } |
230 |
227 |
231 @Override |
228 @Override |