| 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 [primitive]. |
| 441 ir.Primitive addPrimitive(ir.Primitive primitive) { |
| 442 add(new ir.LetPrim(primitive)); |
| 443 return primitive; |
| 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 ir.Primitive value = |
| 2022 add(new ir.LetPrim(get)); | 2022 addPrimitive(new ir.GetMutableVariable(mutableVariable)); |
| 2023 environment.update(loopVariable, get); | 2023 environment.update(loopVariable, value); |
| 2024 dartState.registerizedMutableVariables.add(loopVariable); | 2024 dartState.registerizedMutableVariables.add(loopVariable); |
| 2025 } | 2025 } |
| 2026 } | 2026 } |
| 2027 } | 2027 } |
| 2028 | 2028 |
| 2029 void _createFunctionParameter(ParameterElement parameterElement) { | 2029 void _createFunctionParameter(ParameterElement parameterElement) { |
| 2030 ir.Parameter parameter = new ir.Parameter(parameterElement); | 2030 ir.Parameter parameter = new ir.Parameter(parameterElement); |
| 2031 _parameters.add(parameter); | 2031 _parameters.add(parameter); |
| 2032 if (isInMutableVariable(parameterElement)) { | 2032 if (isInMutableVariable(parameterElement)) { |
| 2033 state.functionParameters.add(getMutableVariable(parameterElement)); | 2033 state.functionParameters.add(getMutableVariable(parameterElement)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2053 } | 2053 } |
| 2054 | 2054 |
| 2055 /// Add [functionElement] to the environment with provided [definition]. | 2055 /// Add [functionElement] to the environment with provided [definition]. |
| 2056 void declareLocalFunction(LocalFunctionElement functionElement, | 2056 void declareLocalFunction(LocalFunctionElement functionElement, |
| 2057 ir.FunctionDefinition definition) { | 2057 ir.FunctionDefinition definition) { |
| 2058 assert(isOpen); | 2058 assert(isOpen); |
| 2059 if (isInMutableVariable(functionElement)) { | 2059 if (isInMutableVariable(functionElement)) { |
| 2060 ir.MutableVariable variable = getMutableVariable(functionElement); | 2060 ir.MutableVariable variable = getMutableVariable(functionElement); |
| 2061 add(new ir.DeclareFunction(variable, definition)); | 2061 add(new ir.DeclareFunction(variable, definition)); |
| 2062 } else { | 2062 } else { |
| 2063 ir.CreateFunction prim = new ir.CreateFunction(definition); | 2063 ir.CreateFunction prim = addPrimitive(new ir.CreateFunction(definition)); |
| 2064 add(new ir.LetPrim(prim)); | |
| 2065 environment.extend(functionElement, prim); | 2064 environment.extend(functionElement, prim); |
| 2066 prim.useElementAsHint(functionElement); | 2065 prim.useElementAsHint(functionElement); |
| 2067 } | 2066 } |
| 2068 } | 2067 } |
| 2069 | 2068 |
| 2070 /// Create a function expression from [definition]. | 2069 /// Create a function expression from [definition]. |
| 2071 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { | 2070 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { |
| 2072 ir.CreateFunction prim = new ir.CreateFunction(definition); | 2071 return addPrimitive(new ir.CreateFunction(definition)); |
| 2073 add(new ir.LetPrim(prim)); | |
| 2074 return prim; | |
| 2075 } | 2072 } |
| 2076 | 2073 |
| 2077 /// Create a read access of [local]. | 2074 /// Create a read access of [local]. |
| 2078 ir.Primitive buildLocalGet(LocalElement local) { | 2075 ir.Primitive buildLocalGet(LocalElement local) { |
| 2079 assert(isOpen); | 2076 assert(isOpen); |
| 2080 if (isInMutableVariable(local)) { | 2077 if (isInMutableVariable(local)) { |
| 2081 // Do not use [local] as a hint on [result]. The variable should always | 2078 // Do not use [local] as a hint on [result]. The variable should always |
| 2082 // be inlined, but the hint prevents it. | 2079 // be inlined, but the hint prevents it. |
| 2083 ir.Primitive result = | 2080 return addPrimitive(new ir.GetMutableVariable(getMutableVariable(local))); |
| 2084 new ir.GetMutableVariable(getMutableVariable(local)); | |
| 2085 add(new ir.LetPrim(result)); | |
| 2086 return result; | |
| 2087 } else { | 2081 } else { |
| 2088 return environment.lookup(local); | 2082 return environment.lookup(local); |
| 2089 } | 2083 } |
| 2090 } | 2084 } |
| 2091 | 2085 |
| 2092 /// Create a write access to [local] with the provided [value]. | 2086 /// Create a write access to [local] with the provided [value]. |
| 2093 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { | 2087 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { |
| 2094 assert(isOpen); | 2088 assert(isOpen); |
| 2095 if (isInMutableVariable(local)) { | 2089 if (isInMutableVariable(local)) { |
| 2096 add(new ir.SetMutableVariable(getMutableVariable(local), value)); | 2090 add(new ir.SetMutableVariable(getMutableVariable(local), value)); |
| 2097 } else { | 2091 } else { |
| 2098 value.useElementAsHint(local); | 2092 value.useElementAsHint(local); |
| 2099 environment.update(local, value); | 2093 environment.update(local, value); |
| 2100 } | 2094 } |
| 2101 return value; | 2095 return value; |
| 2102 } | 2096 } |
| 2103 | 2097 |
| 2104 ir.Primitive buildThis() { | 2098 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 | 2099 |
| 2110 ir.Primitive buildSuperInvocation(Element target, | 2100 ir.Primitive buildSuperInvocation(Element target, |
| 2111 Selector selector, | 2101 Selector selector, |
| 2112 List<ir.Primitive> arguments) { | 2102 List<ir.Primitive> arguments) { |
| 2113 return _buildInvokeSuper(target, selector, arguments); | 2103 return _buildInvokeSuper(target, selector, arguments); |
| 2114 } | 2104 } |
| 2115 | 2105 |
| 2116 } | 2106 } |
| 2117 | 2107 |
| 2118 /// State shared between JsIrBuilders within the same function. | 2108 /// State shared between JsIrBuilders within the same function. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2145 Map<ast.TryStatement, TryStatementInfo> get tryStatements => null; | 2135 Map<ast.TryStatement, TryStatementInfo> get tryStatements => null; |
| 2146 Set<Local> get mutableCapturedVariables => null; | 2136 Set<Local> get mutableCapturedVariables => null; |
| 2147 bool isInMutableVariable(Local local) => false; | 2137 bool isInMutableVariable(Local local) => false; |
| 2148 void makeMutableVariable(Local local) {} | 2138 void makeMutableVariable(Local local) {} |
| 2149 void removeMutableVariable(Local local) {} | 2139 void removeMutableVariable(Local local) {} |
| 2150 | 2140 |
| 2151 void _enterClosureEnvironment(ClosureEnvironment env) { | 2141 void _enterClosureEnvironment(ClosureEnvironment env) { |
| 2152 if (env == null) return; | 2142 if (env == null) return; |
| 2153 | 2143 |
| 2154 // Obtain a reference to the function object (this). | 2144 // Obtain a reference to the function object (this). |
| 2155 ir.Primitive thisPrim = new ir.This(); | 2145 ir.Primitive thisPrim = addPrimitive(new ir.This()); |
| 2156 add(new ir.LetPrim(thisPrim)); | |
| 2157 | 2146 |
| 2158 // Obtain access to the free variables. | 2147 // Obtain access to the free variables. |
| 2159 env.freeVariables.forEach((Local local, ClosureLocation location) { | 2148 env.freeVariables.forEach((Local local, ClosureLocation location) { |
| 2160 if (location.isBox) { | 2149 if (location.isBox) { |
| 2161 // Boxed variables are loaded from their box on-demand. | 2150 // Boxed variables are loaded from their box on-demand. |
| 2162 jsState.boxedVariables[local] = location; | 2151 jsState.boxedVariables[local] = location; |
| 2163 } else { | 2152 } else { |
| 2164 // Unboxed variables are loaded from the function object immediately. | 2153 // Unboxed variables are loaded from the function object immediately. |
| 2165 // This includes BoxLocals which are themselves unboxed variables. | 2154 // This includes BoxLocals which are themselves unboxed variables. |
| 2166 ir.Primitive load = new ir.GetField(thisPrim, location.field); | 2155 environment.extend(local, |
| 2167 add(new ir.LetPrim(load)); | 2156 addPrimitive(new ir.GetField(thisPrim, location.field))); |
| 2168 environment.extend(local, load); | |
| 2169 } | 2157 } |
| 2170 }); | 2158 }); |
| 2171 | 2159 |
| 2172 // If the function captures a reference to the receiver from the | 2160 // If the function captures a reference to the receiver from the |
| 2173 // enclosing method, remember which primitive refers to the receiver object. | 2161 // enclosing method, remember which primitive refers to the receiver object. |
| 2174 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) { | 2162 if (env.thisLocal != null && env.freeVariables.containsKey(env.thisLocal)) { |
| 2175 jsState.receiver = environment.lookup(env.thisLocal); | 2163 jsState.receiver = environment.lookup(env.thisLocal); |
| 2176 } | 2164 } |
| 2177 | 2165 |
| 2178 // If the function has a self-reference, use the value of `this`. | 2166 // If the function has a self-reference, use the value of `this`. |
| 2179 if (env.selfReference != null) { | 2167 if (env.selfReference != null) { |
| 2180 environment.extend(env.selfReference, thisPrim); | 2168 environment.extend(env.selfReference, thisPrim); |
| 2181 } | 2169 } |
| 2182 } | 2170 } |
| 2183 | 2171 |
| 2184 /// Creates a box for [scope.box] and binds the captured variables to | 2172 /// Creates a box for [scope.box] and binds the captured variables to |
| 2185 /// that box. | 2173 /// that box. |
| 2186 /// | 2174 /// |
| 2187 /// The captured variables can subsequently be manipulated with | 2175 /// The captured variables can subsequently be manipulated with |
| 2188 /// [declareLocalVariable], [buildLocalGet], and [buildLocalSet]. | 2176 /// [declareLocalVariable], [buildLocalGet], and [buildLocalSet]. |
| 2189 void enterScope(ClosureScope scope) => _enterScope(scope); | 2177 void enterScope(ClosureScope scope) => _enterScope(scope); |
| 2190 | 2178 |
| 2191 void _enterScope(ClosureScope scope) { | 2179 void _enterScope(ClosureScope scope) { |
| 2192 if (scope == null) return; | 2180 if (scope == null) return; |
| 2193 ir.CreateBox boxPrim = new ir.CreateBox(); | 2181 ir.CreateBox boxPrim = addPrimitive(new ir.CreateBox()); |
| 2194 add(new ir.LetPrim(boxPrim)); | |
| 2195 environment.extend(scope.box, boxPrim); | 2182 environment.extend(scope.box, boxPrim); |
| 2196 boxPrim.useElementAsHint(scope.box); | 2183 boxPrim.useElementAsHint(scope.box); |
| 2197 scope.capturedVariables.forEach((Local local, ClosureLocation location) { | 2184 scope.capturedVariables.forEach((Local local, ClosureLocation location) { |
| 2198 assert(!jsState.boxedVariables.containsKey(local)); | 2185 assert(!jsState.boxedVariables.containsKey(local)); |
| 2199 if (location.isBox) { | 2186 if (location.isBox) { |
| 2200 jsState.boxedVariables[local] = location; | 2187 jsState.boxedVariables[local] = location; |
| 2201 } | 2188 } |
| 2202 }); | 2189 }); |
| 2203 } | 2190 } |
| 2204 | 2191 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2243 ir.Primitive buildFunctionExpression(ClosureClassElement classElement) { | 2230 ir.Primitive buildFunctionExpression(ClosureClassElement classElement) { |
| 2244 List<ir.Primitive> arguments = <ir.Primitive>[]; | 2231 List<ir.Primitive> arguments = <ir.Primitive>[]; |
| 2245 for (ClosureFieldElement field in classElement.closureFields) { | 2232 for (ClosureFieldElement field in classElement.closureFields) { |
| 2246 // Captured 'this' is not available as a local in the current environment, | 2233 // Captured 'this' is not available as a local in the current environment, |
| 2247 // so treat that specially. | 2234 // so treat that specially. |
| 2248 ir.Primitive value = field.local is ThisLocal | 2235 ir.Primitive value = field.local is ThisLocal |
| 2249 ? buildThis() | 2236 ? buildThis() |
| 2250 : environment.lookup(field.local); | 2237 : environment.lookup(field.local); |
| 2251 arguments.add(value); | 2238 arguments.add(value); |
| 2252 } | 2239 } |
| 2253 ir.Primitive closure = new ir.CreateInstance(classElement, arguments); | 2240 return addPrimitive(new ir.CreateInstance(classElement, arguments)); |
| 2254 add(new ir.LetPrim(closure)); | |
| 2255 return closure; | |
| 2256 } | 2241 } |
| 2257 | 2242 |
| 2258 /// Create a read access of [local]. | 2243 /// Create a read access of [local]. |
| 2259 ir.Primitive buildLocalGet(LocalElement local) { | 2244 ir.Primitive buildLocalGet(LocalElement local) { |
| 2260 assert(isOpen); | 2245 assert(isOpen); |
| 2261 ClosureLocation location = jsState.boxedVariables[local]; | 2246 ClosureLocation location = jsState.boxedVariables[local]; |
| 2262 if (location != null) { | 2247 if (location != null) { |
| 2263 ir.Primitive result = new ir.GetField(environment.lookup(location.box), | 2248 ir.Primitive result = new ir.GetField(environment.lookup(location.box), |
| 2264 location.field); | 2249 location.field); |
| 2265 result.useElementAsHint(local); | 2250 result.useElementAsHint(local); |
| 2266 add(new ir.LetPrim(result)); | 2251 return addPrimitive(result); |
| 2267 return result; | |
| 2268 } else { | 2252 } else { |
| 2269 return environment.lookup(local); | 2253 return environment.lookup(local); |
| 2270 } | 2254 } |
| 2271 } | 2255 } |
| 2272 | 2256 |
| 2273 /// Create a write access to [local] with the provided [value]. | 2257 /// Create a write access to [local] with the provided [value]. |
| 2274 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { | 2258 ir.Primitive buildLocalSet(LocalElement local, ir.Primitive value) { |
| 2275 assert(isOpen); | 2259 assert(isOpen); |
| 2276 ClosureLocation location = jsState.boxedVariables[local]; | 2260 ClosureLocation location = jsState.boxedVariables[local]; |
| 2277 if (location != null) { | 2261 if (location != null) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2303 _enterScope(scope); | 2287 _enterScope(scope); |
| 2304 } | 2288 } |
| 2305 | 2289 |
| 2306 void _enterForLoopUpdate(ClosureScope scope, | 2290 void _enterForLoopUpdate(ClosureScope scope, |
| 2307 List<LocalElement> loopVariables) { | 2291 List<LocalElement> loopVariables) { |
| 2308 if (scope == null) return; | 2292 if (scope == null) return; |
| 2309 // If there are no boxed loop variables, then the box is created inside the | 2293 // 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. | 2294 // body, so there is no need to explicitly renew it. |
| 2311 if (scope.boxedLoopVariables.isEmpty) return; | 2295 if (scope.boxedLoopVariables.isEmpty) return; |
| 2312 ir.Primitive box = environment.lookup(scope.box); | 2296 ir.Primitive box = environment.lookup(scope.box); |
| 2313 ir.Primitive newBox = new ir.CreateBox(); | 2297 ir.Primitive newBox = addPrimitive(new ir.CreateBox()); |
| 2314 newBox.useElementAsHint(scope.box); | 2298 newBox.useElementAsHint(scope.box); |
| 2315 add(new ir.LetPrim(newBox)); | |
| 2316 for (VariableElement loopVar in scope.boxedLoopVariables) { | 2299 for (VariableElement loopVar in scope.boxedLoopVariables) { |
| 2317 ClosureLocation location = scope.capturedVariables[loopVar]; | 2300 ClosureLocation location = scope.capturedVariables[loopVar]; |
| 2318 ir.Primitive get = new ir.GetField(box, location.field); | 2301 ir.Primitive value = addPrimitive(new ir.GetField(box, location.field)); |
| 2319 add(new ir.LetPrim(get)); | 2302 add(new ir.SetField(newBox, location.field, value)); |
| 2320 add(new ir.SetField(newBox, location.field, get)); | |
| 2321 } | 2303 } |
| 2322 environment.update(scope.box, newBox); | 2304 environment.update(scope.box, newBox); |
| 2323 } | 2305 } |
| 2324 | 2306 |
| 2325 ir.Primitive buildThis() { | 2307 ir.Primitive buildThis() { |
| 2326 if (jsState.receiver != null) return jsState.receiver; | 2308 if (jsState.receiver != null) return jsState.receiver; |
| 2327 ir.Primitive thisPrim = new ir.This(); | 2309 return addPrimitive(new ir.This()); |
| 2328 add(new ir.LetPrim(thisPrim)); | |
| 2329 return thisPrim; | |
| 2330 } | 2310 } |
| 2331 | 2311 |
| 2332 ir.Primitive buildSuperInvocation(Element target, | 2312 ir.Primitive buildSuperInvocation(Element target, |
| 2333 Selector selector, | 2313 Selector selector, |
| 2334 List<ir.Primitive> arguments) { | 2314 List<ir.Primitive> arguments) { |
| 2335 // Direct calls to FieldElements are currently problematic because the | 2315 // Direct calls to FieldElements are currently problematic because the |
| 2336 // backend will not issue a getter for the field unless it finds a dynamic | 2316 // backend will not issue a getter for the field unless it finds a dynamic |
| 2337 // access that matches its getter. | 2317 // access that matches its getter. |
| 2338 // As a workaround, we generate GetField for this case, although ideally | 2318 // As a workaround, we generate GetField for this case, although ideally |
| 2339 // this should be the result of inlining the field's getter. | 2319 // this should be the result of inlining the field's getter. |
| 2340 if (target is FieldElement) { | 2320 if (target is FieldElement) { |
| 2341 if (selector.isGetter) { | 2321 if (selector.isGetter) { |
| 2342 ir.Primitive get = new ir.GetField(buildThis(), target); | 2322 return addPrimitive(new ir.GetField(buildThis(), target)); |
| 2343 add(new ir.LetPrim(get)); | |
| 2344 return get; | |
| 2345 } else { | 2323 } else { |
| 2346 assert(selector.isSetter); | 2324 assert(selector.isSetter); |
| 2347 add(new ir.SetField(buildThis(), target, arguments.single)); | 2325 add(new ir.SetField(buildThis(), target, arguments.single)); |
| 2348 return arguments.single; | 2326 return arguments.single; |
| 2349 } | 2327 } |
| 2350 } else { | 2328 } else { |
| 2351 return _buildInvokeSuper(target, selector, arguments); | 2329 return _buildInvokeSuper(target, selector, arguments); |
| 2352 } | 2330 } |
| 2353 } | 2331 } |
| 2354 | 2332 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2442 // TODO(johnniwinther): Support passing of [DartType] for the exception. | 2420 // TODO(johnniwinther): Support passing of [DartType] for the exception. |
| 2443 class CatchClauseInfo { | 2421 class CatchClauseInfo { |
| 2444 final LocalVariableElement exceptionVariable; | 2422 final LocalVariableElement exceptionVariable; |
| 2445 final LocalVariableElement stackTraceVariable; | 2423 final LocalVariableElement stackTraceVariable; |
| 2446 final SubbuildFunction buildCatchBlock; | 2424 final SubbuildFunction buildCatchBlock; |
| 2447 | 2425 |
| 2448 CatchClauseInfo({this.exceptionVariable, | 2426 CatchClauseInfo({this.exceptionVariable, |
| 2449 this.stackTraceVariable, | 2427 this.stackTraceVariable, |
| 2450 this.buildCatchBlock}); | 2428 this.buildCatchBlock}); |
| 2451 } | 2429 } |
| OLD | NEW |