Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.ir_builder; | 5 library dart2js.ir_builder; |
| 6 | 6 |
| 7 import '../constants/expressions.dart'; | 7 import '../constants/expressions.dart'; |
| 8 import '../constants/values.dart' show PrimitiveConstantValue; | 8 import '../constants/values.dart' show PrimitiveConstantValue; |
| 9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../dart2jslib.dart'; | 10 import '../dart2jslib.dart'; |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 return parameter; | 416 return parameter; |
| 417 } | 417 } |
| 418 | 418 |
| 419 /// Adds the constant [variableElement] to the environment with [value] as its | 419 /// Adds the constant [variableElement] to the environment with [value] as its |
| 420 /// constant value. | 420 /// constant value. |
| 421 void declareLocalConstant(LocalVariableElement variableElement, | 421 void declareLocalConstant(LocalVariableElement variableElement, |
| 422 ConstantExpression value) { | 422 ConstantExpression value) { |
| 423 state.localConstants.add(new ConstDeclaration(variableElement, value)); | 423 state.localConstants.add(new ConstDeclaration(variableElement, value)); |
| 424 } | 424 } |
| 425 | 425 |
| 426 // Plug an expression into the 'hole' in the context being accumulated. The | 426 /// Plug an expression into the 'hole' in the context being accumulated. The |
| 427 // empty context (just a hole) is represented by root (and current) being | 427 /// empty context (just a hole) is represented by root (and current) being |
| 428 // null. Since the hole in the current context is filled by this function, | 428 /// null. Since the hole in the current context is filled by this function, |
| 429 // the new hole must be in the newly added expression---which becomes the | 429 /// the new hole must be in the newly added expression---which becomes the |
| 430 // new value of current. | 430 /// new value of current. |
| 431 void add(ir.Expression expr) { | 431 void add(ir.Expression expr) { |
| 432 assert(isOpen); | 432 assert(isOpen); |
| 433 if (_root == null) { | 433 if (_root == null) { |
| 434 _root = _current = expr; | 434 _root = _current = expr; |
| 435 } else { | 435 } else { |
| 436 _current = _current.plug(expr); | 436 _current = _current.plug(expr); |
| 437 } | 437 } |
| 438 } | 438 } |
| 439 | 439 |
| 440 /// Create and add a new [LetPrim] for [expression]. | |
|
Kevin Millikin (Google)
2015/03/18 12:50:40
Call the argument primitive.
| |
| 441 ir.Primitive addPrimitive(ir.Primitive expression) { | |
| 442 add(new ir.LetPrim(expression)); | |
| 443 return expression; | |
| 444 } | |
| 445 | |
| 440 ir.Primitive _continueWithExpression(ir.Expression build(ir.Continuation k)) { | 446 ir.Primitive _continueWithExpression(ir.Expression build(ir.Continuation k)) { |
| 441 ir.Parameter v = new ir.Parameter(null); | 447 ir.Parameter v = new ir.Parameter(null); |
| 442 ir.Continuation k = new ir.Continuation([v]); | 448 ir.Continuation k = new ir.Continuation([v]); |
| 443 ir.Expression expression = build(k); | 449 ir.Expression expression = build(k); |
| 444 add(new ir.LetCont(k, expression)); | 450 add(new ir.LetCont(k, expression)); |
| 445 return v; | 451 return v; |
| 446 } | 452 } |
| 447 | 453 |
| 448 ir.Primitive _buildInvokeStatic(Element element, | 454 ir.Primitive _buildInvokeStatic(Element element, |
| 449 Selector selector, | 455 Selector selector, |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 478 Selector callSelector = new Selector.callClosure( | 484 Selector callSelector = new Selector.callClosure( |
| 479 selector.argumentCount, | 485 selector.argumentCount, |
| 480 selector.namedArguments); | 486 selector.namedArguments); |
| 481 return _buildInvokeDynamic(target, callSelector, arguments); | 487 return _buildInvokeDynamic(target, callSelector, arguments); |
| 482 } | 488 } |
| 483 | 489 |
| 484 | 490 |
| 485 /// Create a constant literal from [constant]. | 491 /// Create a constant literal from [constant]. |
| 486 ir.Constant buildConstantLiteral(ConstantExpression constant) { | 492 ir.Constant buildConstantLiteral(ConstantExpression constant) { |
| 487 assert(isOpen); | 493 assert(isOpen); |
| 488 ir.Constant prim = new ir.Constant(constant); | 494 return addPrimitive(new ir.Constant(constant)); |
| 489 add(new ir.LetPrim(prim)); | |
| 490 return prim; | |
| 491 } | 495 } |
| 492 | 496 |
| 493 // Helper for building primitive literals. | 497 // Helper for building primitive literals. |
| 494 ir.Constant _buildPrimitiveConstant(PrimitiveConstantValue constant) { | 498 ir.Constant _buildPrimitiveConstant(PrimitiveConstantValue constant) { |
| 495 return buildConstantLiteral(new PrimitiveConstantExpression(constant)); | 499 return buildConstantLiteral(new PrimitiveConstantExpression(constant)); |
| 496 } | 500 } |
| 497 | 501 |
| 498 /// Create an integer literal. | 502 /// Create an integer literal. |
| 499 ir.Constant buildIntegerLiteral(int value) { | 503 ir.Constant buildIntegerLiteral(int value) { |
| 500 return _buildPrimitiveConstant(state.constantSystem.createInt(value)); | 504 return _buildPrimitiveConstant(state.constantSystem.createInt(value)); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 519 ir.Constant buildStringLiteral(String value) { | 523 ir.Constant buildStringLiteral(String value) { |
| 520 return _buildPrimitiveConstant( | 524 return _buildPrimitiveConstant( |
| 521 state.constantSystem.createString(new ast.DartString.literal(value))); | 525 state.constantSystem.createString(new ast.DartString.literal(value))); |
| 522 } | 526 } |
| 523 | 527 |
| 524 /// Creates a non-constant list literal of the provided [type] and with the | 528 /// Creates a non-constant list literal of the provided [type] and with the |
| 525 /// provided [values]. | 529 /// provided [values]. |
| 526 ir.Primitive buildListLiteral(InterfaceType type, | 530 ir.Primitive buildListLiteral(InterfaceType type, |
| 527 Iterable<ir.Primitive> values) { | 531 Iterable<ir.Primitive> values) { |
| 528 assert(isOpen); | 532 assert(isOpen); |
| 529 ir.Primitive result = new ir.LiteralList(type, values); | 533 return addPrimitive(new ir.LiteralList(type, values)); |
| 530 add(new ir.LetPrim(result)); | |
| 531 return result; | |
| 532 } | 534 } |
| 533 | 535 |
| 534 /// Creates a non-constant map literal of the provided [type] and with the | 536 /// Creates a non-constant map literal of the provided [type] and with the |
| 535 /// entries build from the [keys] and [values] using [build]. | 537 /// entries build from the [keys] and [values] using [build]. |
| 536 ir.Primitive buildMapLiteral(InterfaceType type, | 538 ir.Primitive buildMapLiteral(InterfaceType type, |
| 537 Iterable keys, | 539 Iterable keys, |
| 538 Iterable values, | 540 Iterable values, |
| 539 BuildFunction build) { | 541 BuildFunction build) { |
| 540 assert(isOpen); | 542 assert(isOpen); |
| 541 List<ir.LiteralMapEntry> entries = <ir.LiteralMapEntry>[]; | 543 List<ir.LiteralMapEntry> entries = <ir.LiteralMapEntry>[]; |
| 542 Iterator key = keys.iterator; | 544 Iterator key = keys.iterator; |
| 543 Iterator value = values.iterator; | 545 Iterator value = values.iterator; |
| 544 while (key.moveNext() && value.moveNext()) { | 546 while (key.moveNext() && value.moveNext()) { |
| 545 entries.add(new ir.LiteralMapEntry( | 547 entries.add(new ir.LiteralMapEntry( |
| 546 build(key.current), build(value.current))); | 548 build(key.current), build(value.current))); |
| 547 } | 549 } |
| 548 assert(!key.moveNext() && !value.moveNext()); | 550 assert(!key.moveNext() && !value.moveNext()); |
| 549 ir.Primitive result = new ir.LiteralMap(type, entries); | 551 return addPrimitive(new ir.LiteralMap(type, entries)); |
| 550 add(new ir.LetPrim(result)); | |
| 551 return result; | |
| 552 } | 552 } |
| 553 | 553 |
| 554 /// Creates a conditional expression with the provided [condition] where the | 554 /// Creates a conditional expression with the provided [condition] where the |
| 555 /// then and else expression are created through the [buildThenExpression] and | 555 /// then and else expression are created through the [buildThenExpression] and |
| 556 /// [buildElseExpression] functions, respectively. | 556 /// [buildElseExpression] functions, respectively. |
| 557 ir.Primitive buildConditional( | 557 ir.Primitive buildConditional( |
| 558 ir.Primitive condition, | 558 ir.Primitive condition, |
| 559 ir.Primitive buildThenExpression(IrBuilder builder), | 559 ir.Primitive buildThenExpression(IrBuilder builder), |
| 560 ir.Primitive buildElseExpression(IrBuilder builder)) { | 560 ir.Primitive buildElseExpression(IrBuilder builder)) { |
| 561 | 561 |
| (...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2011 void _enterForLoopUpdate(ClosureScope scope, | 2011 void _enterForLoopUpdate(ClosureScope scope, |
| 2012 List<LocalElement> loopVariables) { | 2012 List<LocalElement> loopVariables) { |
| 2013 assert(scope == null); | 2013 assert(scope == null); |
| 2014 // Move captured loop variables back into the local environment. | 2014 // Move captured loop variables back into the local environment. |
| 2015 // The update expression will use the values we put in the environment, | 2015 // The update expression will use the values we put in the environment, |
| 2016 // and then the environments for the initializer and update will be | 2016 // and then the environments for the initializer and update will be |
| 2017 // joined at the head of the body. | 2017 // joined at the head of the body. |
| 2018 for (LocalElement loopVariable in loopVariables) { | 2018 for (LocalElement loopVariable in loopVariables) { |
| 2019 if (isInMutableVariable(loopVariable)) { | 2019 if (isInMutableVariable(loopVariable)) { |
| 2020 ir.MutableVariable mutableVariable = getMutableVariable(loopVariable); | 2020 ir.MutableVariable mutableVariable = getMutableVariable(loopVariable); |
| 2021 ir.Primitive get = new ir.GetMutableVariable(mutableVariable); | 2021 environment.update(loopVariable, |
| 2022 add(new ir.LetPrim(get)); | 2022 addPrimitive(new ir.GetMutableVariable(mutableVariable))); |
|
Kevin Millikin (Google)
2015/03/18 12:50:40
I don't really like the side effecting expression
| |
| 2023 environment.update(loopVariable, get); | |
| 2024 dartState.registerizedMutableVariables.add(loopVariable); | 2023 dartState.registerizedMutableVariables.add(loopVariable); |
| 2025 } | 2024 } |
| 2026 } | 2025 } |
| 2027 } | 2026 } |
| 2028 | 2027 |
| 2029 void _createFunctionParameter(ParameterElement parameterElement) { | 2028 void _createFunctionParameter(ParameterElement parameterElement) { |
| 2030 ir.Parameter parameter = new ir.Parameter(parameterElement); | 2029 ir.Parameter parameter = new ir.Parameter(parameterElement); |
| 2031 _parameters.add(parameter); | 2030 _parameters.add(parameter); |
| 2032 if (isInMutableVariable(parameterElement)) { | 2031 if (isInMutableVariable(parameterElement)) { |
| 2033 state.functionParameters.add(getMutableVariable(parameterElement)); | 2032 state.functionParameters.add(getMutableVariable(parameterElement)); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 2053 } | 2052 } |
| 2054 | 2053 |
| 2055 /// Add [functionElement] to the environment with provided [definition]. | 2054 /// Add [functionElement] to the environment with provided [definition]. |
| 2056 void declareLocalFunction(LocalFunctionElement functionElement, | 2055 void declareLocalFunction(LocalFunctionElement functionElement, |
| 2057 ir.FunctionDefinition definition) { | 2056 ir.FunctionDefinition definition) { |
| 2058 assert(isOpen); | 2057 assert(isOpen); |
| 2059 if (isInMutableVariable(functionElement)) { | 2058 if (isInMutableVariable(functionElement)) { |
| 2060 ir.MutableVariable variable = getMutableVariable(functionElement); | 2059 ir.MutableVariable variable = getMutableVariable(functionElement); |
| 2061 add(new ir.DeclareFunction(variable, definition)); | 2060 add(new ir.DeclareFunction(variable, definition)); |
| 2062 } else { | 2061 } else { |
| 2063 ir.CreateFunction prim = new ir.CreateFunction(definition); | 2062 ir.CreateFunction prim = addPrimitive(new ir.CreateFunction(definition)); |
| 2064 add(new ir.LetPrim(prim)); | |
| 2065 environment.extend(functionElement, prim); | 2063 environment.extend(functionElement, prim); |
| 2066 prim.useElementAsHint(functionElement); | 2064 prim.useElementAsHint(functionElement); |
| 2067 } | 2065 } |
| 2068 } | 2066 } |
| 2069 | 2067 |
| 2070 /// Create a function expression from [definition]. | 2068 /// Create a function expression from [definition]. |
| 2071 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { | 2069 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { |
| 2072 ir.CreateFunction prim = new ir.CreateFunction(definition); | 2070 return addPrimitive(new ir.CreateFunction(definition)); |
| 2073 add(new ir.LetPrim(prim)); | |
| 2074 return prim; | |
| 2075 } | 2071 } |
| 2076 | 2072 |
| 2077 /// Create a read access of [local]. | 2073 /// Create a read access of [local]. |
| 2078 ir.Primitive buildLocalGet(LocalElement local) { | 2074 ir.Primitive buildLocalGet(LocalElement local) { |
| 2079 assert(isOpen); | 2075 assert(isOpen); |
| 2080 if (isInMutableVariable(local)) { | 2076 if (isInMutableVariable(local)) { |
| 2081 // Do not use [local] as a hint on [result]. The variable should always | 2077 // Do not use [local] as a hint on [result]. The variable should always |
| 2082 // be inlined, but the hint prevents it. | 2078 // be inlined, but the hint prevents it. |
| 2083 ir.Primitive result = | 2079 return addPrimitive(new ir.GetMutableVariable(getMutableVariable(local))); |
| 2084 new ir.GetMutableVariable(getMutableVariable(local)); | |
| 2085 add(new ir.LetPrim(result)); | |
| 2086 return result; | |
| 2087 } else { | 2080 } else { |
| 2088 return environment.lookup(local); | 2081 return environment.lookup(local); |
| 2089 } | 2082 } |
| 2090 } | 2083 } |
| 2091 | 2084 |
| 2092 /// Create a write access to [local] with the provided [value]. | 2085 /// Create a write access to [local] with the provided [value]. |
| 2093 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { | 2086 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { |
| 2094 assert(isOpen); | 2087 assert(isOpen); |
| 2095 if (isInMutableVariable(local)) { | 2088 if (isInMutableVariable(local)) { |
| 2096 add(new ir.SetMutableVariable(getMutableVariable(local), value)); | 2089 add(new ir.SetMutableVariable(getMutableVariable(local), value)); |
| 2097 } else { | 2090 } else { |
| 2098 value.useElementAsHint(local); | 2091 value.useElementAsHint(local); |
| 2099 environment.update(local, value); | 2092 environment.update(local, value); |
| 2100 } | 2093 } |
| 2101 return value; | 2094 return value; |
| 2102 } | 2095 } |
| 2103 | 2096 |
| 2104 ir.Primitive buildThis() { | 2097 ir.Primitive buildThis() => addPrimitive(new ir.This()); |
| 2105 ir.Primitive thisPrim = new ir.This(); | |
| 2106 add(new ir.LetPrim(thisPrim)); | |
| 2107 return thisPrim; | |
| 2108 } | |
| 2109 | 2098 |
| 2110 ir.Primitive buildSuperInvocation(Element target, | 2099 ir.Primitive buildSuperInvocation(Element target, |
| 2111 Selector selector, | 2100 Selector selector, |
| 2112 List<ir.Primitive> arguments) { | 2101 List<ir.Primitive> arguments) { |
| 2113 return _buildInvokeSuper(target, selector, arguments); | 2102 return _buildInvokeSuper(target, selector, arguments); |
| 2114 } | 2103 } |
| 2115 | 2104 |
| 2116 } | 2105 } |
| 2117 | 2106 |
| 2118 /// State shared between JsIrBuilders within the same function. | 2107 /// State shared between JsIrBuilders within the same function. |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 2145 Map<ast.TryStatement, TryStatementInfo> get tryStatements => null; | 2134 Map<ast.TryStatement, TryStatementInfo> get tryStatements => null; |
| 2146 Set<Local> get mutableCapturedVariables => null; | 2135 Set<Local> get mutableCapturedVariables => null; |
| 2147 bool isInMutableVariable(Local local) => false; | 2136 bool isInMutableVariable(Local local) => false; |
| 2148 void makeMutableVariable(Local local) {} | 2137 void makeMutableVariable(Local local) {} |
| 2149 void removeMutableVariable(Local local) {} | 2138 void removeMutableVariable(Local local) {} |
| 2150 | 2139 |
| 2151 void _enterClosureEnvironment(ClosureEnvironment env) { | 2140 void _enterClosureEnvironment(ClosureEnvironment env) { |
| 2152 if (env == null) return; | 2141 if (env == null) return; |
| 2153 | 2142 |
| 2154 // Obtain a reference to the function object (this). | 2143 // Obtain a reference to the function object (this). |
| 2155 ir.Primitive thisPrim = new ir.This(); | 2144 ir.Primitive thisPrim = addPrimitive(new ir.This()); |
| 2156 add(new ir.LetPrim(thisPrim)); | |
| 2157 | 2145 |
| 2158 // Obtain access to the free variables. | 2146 // Obtain access to the free variables. |
| 2159 env.freeVariables.forEach((Local local, ClosureLocation location) { | 2147 env.freeVariables.forEach((Local local, ClosureLocation location) { |
| 2160 if (location.isBox) { | 2148 if (location.isBox) { |
| 2161 // Boxed variables are loaded from their box on-demand. | 2149 // Boxed variables are loaded from their box on-demand. |
| 2162 jsState.boxedVariables[local] = location; | 2150 jsState.boxedVariables[local] = location; |
| 2163 } else { | 2151 } else { |
| 2164 // Unboxed variables are loaded from the function object immediately. | 2152 // Unboxed variables are loaded from the function object immediately. |
| 2165 // This includes BoxLocals which are themselves unboxed variables. | 2153 // This includes BoxLocals which are themselves unboxed variables. |
| 2166 ir.Primitive load = new ir.GetField(thisPrim, location.field); | 2154 environment.extend(local, |
|
Kevin Millikin (Google)
2015/03/18 12:50:40
Likewise here, name the side-effecting subexpressi
| |
| 2167 add(new ir.LetPrim(load)); | 2155 addPrimitive(new ir.GetField(thisPrim, location.field))); |
| 2168 environment.extend(local, load); | |
| 2169 } | 2156 } |
| 2170 }); | 2157 }); |
| 2171 | 2158 |
| 2172 // If the function captures a reference to the receiver from the | 2159 // If the function captures a reference to the receiver from the |
| 2173 // enclosing method, remember which primitive refers to the receiver object. | 2160 // enclosing method, remember which primitive refers to the receiver object. |
| 2174 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) { | 2161 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) { |
| 2175 jsState.receiver = environment.lookup(env.thisLocal); | 2162 jsState.receiver = environment.lookup(env.thisLocal); |
| 2176 } | 2163 } |
| 2177 | 2164 |
| 2178 // If the function has a self-reference, use the value of `this`. | 2165 // If the function has a self-reference, use the value of `this`. |
| 2179 if (env.selfReference != null) { | 2166 if (env.selfReference != null) { |
| 2180 environment.extend(env.selfReference, thisPrim); | 2167 environment.extend(env.selfReference, thisPrim); |
| 2181 } | 2168 } |
| 2182 } | 2169 } |
| 2183 | 2170 |
| 2184 /// Creates a box for [scope.box] and binds the captured variables to | 2171 /// Creates a box for [scope.box] and binds the captured variables to |
| 2185 /// that box. | 2172 /// that box. |
| 2186 /// | 2173 /// |
| 2187 /// The captured variables can subsequently be manipulated with | 2174 /// The captured variables can subsequently be manipulated with |
| 2188 /// [declareLocalVariable], [buildLocalGet], and [buildLocalSet]. | 2175 /// [declareLocalVariable], [buildLocalGet], and [buildLocalSet]. |
| 2189 void enterScope(ClosureScope scope) => _enterScope(scope); | 2176 void enterScope(ClosureScope scope) => _enterScope(scope); |
| 2190 | 2177 |
| 2191 void _enterScope(ClosureScope scope) { | 2178 void _enterScope(ClosureScope scope) { |
| 2192 if (scope == null) return; | 2179 if (scope == null) return; |
| 2193 ir.CreateBox boxPrim = new ir.CreateBox(); | 2180 ir.CreateBox boxPrim = addPrimitive(new ir.CreateBox()); |
| 2194 add(new ir.LetPrim(boxPrim)); | |
| 2195 environment.extend(scope.box, boxPrim); | 2181 environment.extend(scope.box, boxPrim); |
| 2196 boxPrim.useElementAsHint(scope.box); | 2182 boxPrim.useElementAsHint(scope.box); |
| 2197 scope.capturedVariables.forEach((Local local, ClosureLocation location) { | 2183 scope.capturedVariables.forEach((Local local, ClosureLocation location) { |
| 2198 assert(!jsState.boxedVariables.containsKey(local)); | 2184 assert(!jsState.boxedVariables.containsKey(local)); |
| 2199 if (location.isBox) { | 2185 if (location.isBox) { |
| 2200 jsState.boxedVariables[local] = location; | 2186 jsState.boxedVariables[local] = location; |
| 2201 } | 2187 } |
| 2202 }); | 2188 }); |
| 2203 } | 2189 } |
| 2204 | 2190 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2243 ir.Primitive buildFunctionExpression(ClosureClassElement classElement) { | 2229 ir.Primitive buildFunctionExpression(ClosureClassElement classElement) { |
| 2244 List<ir.Primitive> arguments = <ir.Primitive>[]; | 2230 List<ir.Primitive> arguments = <ir.Primitive>[]; |
| 2245 for (ClosureFieldElement field in classElement.closureFields) { | 2231 for (ClosureFieldElement field in classElement.closureFields) { |
| 2246 // Captured 'this' is not available as a local in the current environment, | 2232 // Captured 'this' is not available as a local in the current environment, |
| 2247 // so treat that specially. | 2233 // so treat that specially. |
| 2248 ir.Primitive value = field.local is ThisLocal | 2234 ir.Primitive value = field.local is ThisLocal |
| 2249 ? buildThis() | 2235 ? buildThis() |
| 2250 : environment.lookup(field.local); | 2236 : environment.lookup(field.local); |
| 2251 arguments.add(value); | 2237 arguments.add(value); |
| 2252 } | 2238 } |
| 2253 ir.Primitive closure = new ir.CreateInstance(classElement, arguments); | 2239 return addPrimitive(new ir.CreateInstance(classElement, arguments)); |
| 2254 add(new ir.LetPrim(closure)); | |
| 2255 return closure; | |
| 2256 } | 2240 } |
| 2257 | 2241 |
| 2258 /// Create a read access of [local]. | 2242 /// Create a read access of [local]. |
| 2259 ir.Primitive buildLocalGet(LocalElement local) { | 2243 ir.Primitive buildLocalGet(LocalElement local) { |
| 2260 assert(isOpen); | 2244 assert(isOpen); |
| 2261 ClosureLocation location = jsState.boxedVariables[local]; | 2245 ClosureLocation location = jsState.boxedVariables[local]; |
| 2262 if (location != null) { | 2246 if (location != null) { |
| 2263 ir.Primitive result = new ir.GetField(environment.lookup(location.box), | 2247 ir.Primitive result = new ir.GetField(environment.lookup(location.box), |
| 2264 location.field); | 2248 location.field); |
| 2265 result.useElementAsHint(local); | 2249 result.useElementAsHint(local); |
| 2266 add(new ir.LetPrim(result)); | 2250 return addPrimitive(result); |
| 2267 return result; | |
| 2268 } else { | 2251 } else { |
| 2269 return environment.lookup(local); | 2252 return environment.lookup(local); |
| 2270 } | 2253 } |
| 2271 } | 2254 } |
| 2272 | 2255 |
| 2273 /// Create a write access to [local] with the provided [value]. | 2256 /// Create a write access to [local] with the provided [value]. |
| 2274 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { | 2257 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { |
| 2275 assert(isOpen); | 2258 assert(isOpen); |
| 2276 ClosureLocation location = jsState.boxedVariables[local]; | 2259 ClosureLocation location = jsState.boxedVariables[local]; |
| 2277 if (location != null) { | 2260 if (location != null) { |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2303 _enterScope(scope); | 2286 _enterScope(scope); |
| 2304 } | 2287 } |
| 2305 | 2288 |
| 2306 void _enterForLoopUpdate(ClosureScope scope, | 2289 void _enterForLoopUpdate(ClosureScope scope, |
| 2307 List<LocalElement> loopVariables) { | 2290 List<LocalElement> loopVariables) { |
| 2308 if (scope == null) return; | 2291 if (scope == null) return; |
| 2309 // If there are no boxed loop variables, then the box is created inside the | 2292 // If there are no boxed loop variables, then the box is created inside the |
| 2310 // body, so there is no need to explicitly renew it. | 2293 // body, so there is no need to explicitly renew it. |
| 2311 if (scope.boxedLoopVariables.isEmpty) return; | 2294 if (scope.boxedLoopVariables.isEmpty) return; |
| 2312 ir.Primitive box = environment.lookup(scope.box); | 2295 ir.Primitive box = environment.lookup(scope.box); |
| 2313 ir.Primitive newBox = new ir.CreateBox(); | 2296 ir.Primitive newBox = addPrimitive(new ir.CreateBox()); |
| 2314 newBox.useElementAsHint(scope.box); | 2297 newBox.useElementAsHint(scope.box); |
| 2315 add(new ir.LetPrim(newBox)); | |
| 2316 for (VariableElement loopVar in scope.boxedLoopVariables) { | 2298 for (VariableElement loopVar in scope.boxedLoopVariables) { |
| 2317 ClosureLocation location = scope.capturedVariables[loopVar]; | 2299 ClosureLocation location = scope.capturedVariables[loopVar]; |
| 2318 ir.Primitive get = new ir.GetField(box, location.field); | 2300 add(new ir.SetField(newBox, location.field, |
| 2319 add(new ir.LetPrim(get)); | 2301 addPrimitive(new ir.GetField(box, location.field)))); |
|
Kevin Millikin (Google)
2015/03/18 12:50:40
And here!
| |
| 2320 add(new ir.SetField(newBox, location.field, get)); | |
| 2321 } | 2302 } |
| 2322 environment.update(scope.box, newBox); | 2303 environment.update(scope.box, newBox); |
| 2323 } | 2304 } |
| 2324 | 2305 |
| 2325 ir.Primitive buildThis() { | 2306 ir.Primitive buildThis() { |
| 2326 if (jsState.receiver != null) return jsState.receiver; | 2307 if (jsState.receiver != null) return jsState.receiver; |
| 2327 ir.Primitive thisPrim = new ir.This(); | 2308 return addPrimitive(new ir.This()); |
| 2328 add(new ir.LetPrim(thisPrim)); | |
| 2329 return thisPrim; | |
| 2330 } | 2309 } |
| 2331 | 2310 |
| 2332 ir.Primitive buildSuperInvocation(Element target, | 2311 ir.Primitive buildSuperInvocation(Element target, |
| 2333 Selector selector, | 2312 Selector selector, |
| 2334 List<ir.Primitive> arguments) { | 2313 List<ir.Primitive> arguments) { |
| 2335 // Direct calls to FieldElements are currently problematic because the | 2314 // Direct calls to FieldElements are currently problematic because the |
| 2336 // backend will not issue a getter for the field unless it finds a dynamic | 2315 // backend will not issue a getter for the field unless it finds a dynamic |
| 2337 // access that matches its getter. | 2316 // access that matches its getter. |
| 2338 // As a workaround, we generate GetField for this case, although ideally | 2317 // As a workaround, we generate GetField for this case, although ideally |
| 2339 // this should be the result of inlining the field's getter. | 2318 // this should be the result of inlining the field's getter. |
| 2340 if (target is FieldElement) { | 2319 if (target is FieldElement) { |
| 2341 if (selector.isGetter) { | 2320 if (selector.isGetter) { |
| 2342 ir.Primitive get = new ir.GetField(buildThis(), target); | 2321 return addPrimitive(new ir.GetField(buildThis(), target)); |
| 2343 add(new ir.LetPrim(get)); | |
| 2344 return get; | |
| 2345 } else { | 2322 } else { |
| 2346 assert(selector.isSetter); | 2323 assert(selector.isSetter); |
| 2347 add(new ir.SetField(buildThis(), target, arguments.single)); | 2324 add(new ir.SetField(buildThis(), target, arguments.single)); |
| 2348 return arguments.single; | 2325 return arguments.single; |
| 2349 } | 2326 } |
| 2350 } else { | 2327 } else { |
| 2351 return _buildInvokeSuper(target, selector, arguments); | 2328 return _buildInvokeSuper(target, selector, arguments); |
| 2352 } | 2329 } |
| 2353 } | 2330 } |
| 2354 | 2331 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2442 // TODO(johnniwinther): Support passing of [DartType] for the exception. | 2419 // TODO(johnniwinther): Support passing of [DartType] for the exception. |
| 2443 class CatchClauseInfo { | 2420 class CatchClauseInfo { |
| 2444 final LocalVariableElement exceptionVariable; | 2421 final LocalVariableElement exceptionVariable; |
| 2445 final LocalVariableElement stackTraceVariable; | 2422 final LocalVariableElement stackTraceVariable; |
| 2446 final SubbuildFunction buildCatchBlock; | 2423 final SubbuildFunction buildCatchBlock; |
| 2447 | 2424 |
| 2448 CatchClauseInfo({this.exceptionVariable, | 2425 CatchClauseInfo({this.exceptionVariable, |
| 2449 this.stackTraceVariable, | 2426 this.stackTraceVariable, |
| 2450 this.buildCatchBlock}); | 2427 this.buildCatchBlock}); |
| 2451 } | 2428 } |
| OLD | NEW |