Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(750)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart

Issue 1011403003: cps-ir: Set runtime type information for new objects that require it. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update comment. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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';
11 import '../elements/elements.dart'; 11 import '../elements/elements.dart';
12 import '../io/source_information.dart'; 12 import '../io/source_information.dart';
13 import '../tree/tree.dart' as ast; 13 import '../tree/tree.dart' as ast;
14 import '../closure.dart' hide ClosureScope; 14 import '../closure.dart' hide ClosureScope;
15 import 'cps_ir_nodes.dart' as ir; 15 import 'cps_ir_nodes.dart' as ir;
16 import 'cps_ir_builder_task.dart' show DartCapturedVariables; 16 import 'cps_ir_builder_task.dart' show DartCapturedVariables,
17 GlobalProgramInformation;
17 18
18 /// A mapping from variable elements to their compile-time values. 19 /// A mapping from variable elements to their compile-time values.
19 /// 20 ///
20 /// Map elements denoted by parameters and local variables to the 21 /// Map elements denoted by parameters and local variables to the
21 /// [ir.Primitive] that is their value. Parameters and locals are 22 /// [ir.Primitive] that is their value. Parameters and locals are
22 /// assigned indexes which can be used to refer to them. 23 /// assigned indexes which can be used to refer to them.
23 class Environment { 24 class Environment {
24 /// A map from locals to their environment index. 25 /// A map from locals to their environment index.
25 final Map<Local, int> variable2index; 26 final Map<Local, int> variable2index;
26 27
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 /// Called before building the body of a for-loop. 302 /// Called before building the body of a for-loop.
302 void _enterForLoopBody(ClosureScope scope, 303 void _enterForLoopBody(ClosureScope scope,
303 List<LocalElement> loopVariables); 304 List<LocalElement> loopVariables);
304 305
305 /// Called before building the update of a for-loop. 306 /// Called before building the update of a for-loop.
306 void _enterForLoopUpdate(ClosureScope scope, 307 void _enterForLoopUpdate(ClosureScope scope,
307 List<LocalElement> loopVariables); 308 List<LocalElement> loopVariables);
308 309
309 /// Add the given function parameter to the IR, and bind it in the environment 310 /// Add the given function parameter to the IR, and bind it in the environment
310 /// or put it in its box, if necessary. 311 /// or put it in its box, if necessary.
311 void _createFunctionParameter(ParameterElement parameterElement); 312 void _createFunctionParameter(Local parameterElement);
312 void _createThisParameter(); 313 void _createThisParameter();
313 314
314 /// Creates an access to the receiver from the current (or enclosing) method. 315 /// Creates an access to the receiver from the current (or enclosing) method.
315 /// 316 ///
316 /// If inside a closure class, [buildThis] will redirect access through 317 /// If inside a closure class, [buildThis] will redirect access through
317 /// closure fields in order to access the receiver from the enclosing method. 318 /// closure fields in order to access the receiver from the enclosing method.
318 ir.Primitive buildThis(); 319 ir.Primitive buildThis();
319 320
320 // TODO(johnniwinther): Make these field final and remove the default values 321 // TODO(johnniwinther): Make these field final and remove the default values
321 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin. 322 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 ..environment = new Environment.empty(); 410 ..environment = new Environment.empty();
410 } 411 }
411 412
412 bool get isOpen => _root == null || _current != null; 413 bool get isOpen => _root == null || _current != null;
413 414
414 415
415 void buildFieldInitializerHeader({ClosureScope closureScope}) { 416 void buildFieldInitializerHeader({ClosureScope closureScope}) {
416 _enterScope(closureScope); 417 _enterScope(closureScope);
417 } 418 }
418 419
419 List<ir.Primitive> buildFunctionHeader(Iterable<ParameterElement> parameters, 420 List<ir.Primitive> buildFunctionHeader(Iterable<Local> parameters,
420 {ClosureScope closureScope, 421 {ClosureScope closureScope,
421 ClosureEnvironment env}) { 422 ClosureEnvironment env}) {
422 _createThisParameter(); 423 _createThisParameter();
423 _enterClosureEnvironment(env); 424 _enterClosureEnvironment(env);
424 _enterScope(closureScope); 425 _enterScope(closureScope);
425 parameters.forEach(_createFunctionParameter); 426 parameters.forEach(_createFunctionParameter);
426 return _parameters; 427 return _parameters;
427 } 428 }
428 429
429 /// Creates a parameter for [local] and adds it to the current environment. 430 /// Creates a parameter for [local] and adds it to the current environment.
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 _buildInvokeStatic( 822 _buildInvokeStatic(
822 element, selector, <ir.Primitive>[value], sourceInformation); 823 element, selector, <ir.Primitive>[value], sourceInformation);
823 return value; 824 return value;
824 } 825 }
825 826
826 /// Create a constructor invocation of [element] on [type] where the 827 /// Create a constructor invocation of [element] on [type] where the
827 /// constructor name and argument structure are defined by [selector] and the 828 /// constructor name and argument structure are defined by [selector] and the
828 /// argument values are defined by [arguments]. 829 /// argument values are defined by [arguments].
829 ir.Primitive buildConstructorInvocation(FunctionElement element, 830 ir.Primitive buildConstructorInvocation(FunctionElement element,
830 Selector selector, 831 Selector selector,
831 DartType type, 832 InterfaceType type,
832 List<ir.Primitive> arguments) { 833 List<ir.Primitive> arguments);
833 assert(isOpen);
834 return _continueWithExpression(
835 (k) => new ir.InvokeConstructor(type, element, selector, k, arguments));
836 }
837 834
838 /// Create a string concatenation of the [arguments]. 835 /// Create a string concatenation of the [arguments].
839 ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments) { 836 ir.Primitive buildStringConcatenation(List<ir.Primitive> arguments) {
840 assert(isOpen); 837 assert(isOpen);
841 return _continueWithExpression( 838 return _continueWithExpression(
842 (k) => new ir.ConcatenateStrings(k, arguments)); 839 (k) => new ir.ConcatenateStrings(k, arguments));
843 } 840 }
844 841
845 /// Create an invocation of the `call` method of [functionExpression], where 842 /// Create an invocation of the `call` method of [functionExpression], where
846 /// the named arguments are given by [selector]. 843 /// the named arguments are given by [selector].
(...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after
2063 if (isInMutableVariable(loopVariable)) { 2060 if (isInMutableVariable(loopVariable)) {
2064 ir.MutableVariable mutableVariable = getMutableVariable(loopVariable); 2061 ir.MutableVariable mutableVariable = getMutableVariable(loopVariable);
2065 ir.Primitive value = 2062 ir.Primitive value =
2066 addPrimitive(new ir.GetMutableVariable(mutableVariable)); 2063 addPrimitive(new ir.GetMutableVariable(mutableVariable));
2067 environment.update(loopVariable, value); 2064 environment.update(loopVariable, value);
2068 dartState.registerizedMutableVariables.add(loopVariable); 2065 dartState.registerizedMutableVariables.add(loopVariable);
2069 } 2066 }
2070 } 2067 }
2071 } 2068 }
2072 2069
2073 void _createFunctionParameter(ParameterElement parameterElement) { 2070 void _createFunctionParameter(Local parameterElement) {
2074 ir.Parameter parameter = new ir.Parameter(parameterElement); 2071 ir.Parameter parameter = new ir.Parameter(parameterElement);
2075 _parameters.add(parameter); 2072 _parameters.add(parameter);
2076 if (isInMutableVariable(parameterElement)) { 2073 if (isInMutableVariable(parameterElement)) {
2077 state.functionParameters.add(getMutableVariable(parameterElement)); 2074 state.functionParameters.add(getMutableVariable(parameterElement));
2078 } else { 2075 } else {
2079 state.functionParameters.add(parameter); 2076 state.functionParameters.add(parameter);
2080 environment.extend(parameterElement, parameter); 2077 environment.extend(parameterElement, parameter);
2081 } 2078 }
2082 } 2079 }
2083 2080
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2162 ir.Primitive buildThis() { 2159 ir.Primitive buildThis() {
2163 return state.enclosingMethodThisParameter; 2160 return state.enclosingMethodThisParameter;
2164 } 2161 }
2165 2162
2166 ir.Primitive buildSuperInvocation(Element target, 2163 ir.Primitive buildSuperInvocation(Element target,
2167 Selector selector, 2164 Selector selector,
2168 List<ir.Primitive> arguments) { 2165 List<ir.Primitive> arguments) {
2169 return _buildInvokeSuper(target, selector, arguments); 2166 return _buildInvokeSuper(target, selector, arguments);
2170 } 2167 }
2171 2168
2169 @override
2170 ir.Primitive buildConstructorInvocation(FunctionElement element,
2171 Selector selector,
2172 InterfaceType type,
2173 List<ir.Primitive> arguments) {
2174 assert(isOpen);
2175 return _continueWithExpression(
2176 (k) => new ir.InvokeConstructor(type, element, selector, k,
2177 arguments));
2178 }
2172 } 2179 }
2173 2180
2174 /// State shared between JsIrBuilders within the same function. 2181 /// State shared between JsIrBuilders within the same function.
2175 /// 2182 ///
2176 /// Note that this is not shared between builders of nested functions. 2183 /// Note that this is not shared between builders of nested functions.
2177 class JsIrBuilderSharedState { 2184 class JsIrBuilderSharedState {
2178 /// Maps boxed locals to their location. These locals are not part of 2185 /// Maps boxed locals to their location. These locals are not part of
2179 /// the environment. 2186 /// the environment.
2180 final Map<Local, ClosureLocation> boxedVariables = {}; 2187 final Map<Local, ClosureLocation> boxedVariables = {};
2181 2188
2182 /// If non-null, this refers to the receiver (`this`) in the enclosing method. 2189 /// If non-null, this refers to the receiver (`this`) in the enclosing method.
2183 ir.Primitive receiver; 2190 ir.Primitive receiver;
2191
2192 /// `true` when we are currently building expressions inside the initializer
2193 /// list of a constructor.
2194 bool inInitializers = false;
2184 } 2195 }
2185 2196
2186 /// JS-specific subclass of [IrBuilder]. 2197 /// JS-specific subclass of [IrBuilder].
2187 /// 2198 ///
2188 /// Inner functions are represented by a [ClosureClassElement], and captured 2199 /// Inner functions are represented by a [ClosureClassElement], and captured
2189 /// variables are boxed as necessary using [CreateBox], [GetField], [SetField]. 2200 /// variables are boxed as necessary using [CreateBox], [GetField], [SetField].
2190 class JsIrBuilder extends IrBuilder { 2201 class JsIrBuilder extends IrBuilder {
2191 final JsIrBuilderSharedState jsState; 2202 final JsIrBuilderSharedState jsState;
2203 final GlobalProgramInformation program;
2192 2204
2193 IrBuilder _makeInstance() => new JsIrBuilder._blank(jsState); 2205 IrBuilder _makeInstance() => new JsIrBuilder._blank(program, jsState);
2194 JsIrBuilder._blank(this.jsState); 2206 JsIrBuilder._blank(this.program, this.jsState);
2195 2207
2196 JsIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement) 2208 JsIrBuilder(this.program, ConstantSystem constantSystem,
2209 ExecutableElement currentElement)
2197 : jsState = new JsIrBuilderSharedState() { 2210 : jsState = new JsIrBuilderSharedState() {
2198 _init(constantSystem, currentElement); 2211 _init(constantSystem, currentElement);
2199 } 2212 }
2200 2213
2201 Map<ast.TryStatement, TryStatementInfo> get tryStatements => null; 2214 Map<ast.TryStatement, TryStatementInfo> get tryStatements => null;
2202 Set<Local> get mutableCapturedVariables => null; 2215 Set<Local> get mutableCapturedVariables => null;
2203 bool isInMutableVariable(Local local) => false; 2216 bool isInMutableVariable(Local local) => false;
2204 void makeMutableVariable(Local local) {} 2217 void makeMutableVariable(Local local) {}
2205 void removeMutableVariable(Local local) {} 2218 void removeMutableVariable(Local local) {}
2206 2219
2220 void enterInitializers() {
2221 assert(jsState.inInitializers == false);
2222 jsState.inInitializers = true;
2223 }
2224
2225 void leaveInitializers() {
2226 assert(jsState.inInitializers == true);
2227 jsState.inInitializers = false;
2228 }
2229
2207 void _enterClosureEnvironment(ClosureEnvironment env) { 2230 void _enterClosureEnvironment(ClosureEnvironment env) {
2208 if (env == null) return; 2231 if (env == null) return;
2209 2232
2210 // Obtain a reference to the function object (this). 2233 // Obtain a reference to the function object (this).
2211 ir.Parameter thisPrim = state.thisParameter; 2234 ir.Parameter thisPrim = state.thisParameter;
2212 2235
2213 // Obtain access to the free variables. 2236 // Obtain access to the free variables.
2214 env.freeVariables.forEach((Local local, ClosureLocation location) { 2237 env.freeVariables.forEach((Local local, ClosureLocation location) {
2215 if (location.isBox) { 2238 if (location.isBox) {
2216 // Boxed variables are loaded from their box on-demand. 2239 // Boxed variables are loaded from their box on-demand.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2248 environment.extend(scope.box, boxPrim); 2271 environment.extend(scope.box, boxPrim);
2249 boxPrim.useElementAsHint(scope.box); 2272 boxPrim.useElementAsHint(scope.box);
2250 scope.capturedVariables.forEach((Local local, ClosureLocation location) { 2273 scope.capturedVariables.forEach((Local local, ClosureLocation location) {
2251 assert(!jsState.boxedVariables.containsKey(local)); 2274 assert(!jsState.boxedVariables.containsKey(local));
2252 if (location.isBox) { 2275 if (location.isBox) {
2253 jsState.boxedVariables[local] = location; 2276 jsState.boxedVariables[local] = location;
2254 } 2277 }
2255 }); 2278 });
2256 } 2279 }
2257 2280
2258 void _createFunctionParameter(ParameterElement parameterElement) { 2281 void _createFunctionParameter(Local parameterElement) {
2259 ir.Parameter parameter = new ir.Parameter(parameterElement); 2282 ir.Parameter parameter = new ir.Parameter(parameterElement);
2260 _parameters.add(parameter); 2283 _parameters.add(parameter);
2261 state.functionParameters.add(parameter); 2284 state.functionParameters.add(parameter);
2262 ClosureLocation location = jsState.boxedVariables[parameterElement]; 2285 ClosureLocation location = jsState.boxedVariables[parameterElement];
2263 if (location != null) { 2286 if (location != null) {
2264 add(new ir.SetField(environment.lookup(location.box), 2287 add(new ir.SetField(environment.lookup(location.box),
2265 location.field, 2288 location.field,
2266 parameter)); 2289 parameter));
2267 } else { 2290 } else {
2268 environment.extend(parameterElement, parameter); 2291 environment.extend(parameterElement, parameter);
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
2423 ClosureScope closureScope) { 2446 ClosureScope closureScope) {
2424 _createThisParameter(); 2447 _createThisParameter();
2425 for (Local param in parameters) { 2448 for (Local param in parameters) {
2426 ir.Parameter parameter = createLocalParameter(param); 2449 ir.Parameter parameter = createLocalParameter(param);
2427 state.functionParameters.add(parameter); 2450 state.functionParameters.add(parameter);
2428 } 2451 }
2429 if (closureScope != null) { 2452 if (closureScope != null) {
2430 jsState.boxedVariables.addAll(closureScope.capturedVariables); 2453 jsState.boxedVariables.addAll(closureScope.capturedVariables);
2431 } 2454 }
2432 } 2455 }
2456
2457 @override
2458 ir.Primitive buildConstructorInvocation(FunctionElement element,
2459 Selector selector,
2460 InterfaceType type,
2461 List<ir.Primitive> arguments) {
2462 assert(isOpen);
2463 // TODO(karlklose): resolve effective target and type here or inline later?
asgerf 2015/03/24 12:37:21 I don't understand this TODO. Please clarify or re
karlklose 2015/03/26 09:50:07 To implement redirecting factory constructors, we
2464 ClassElement cls = element.enclosingClass;
2465 if (program.requiresRuntimeTypesFor(cls)) {
2466 Iterable<ir.Primitive> typeArguments =
2467 type.typeArguments.map((DartType argument) {
2468 return type.treatAsRaw
2469 ? buildNullLiteral()
2470 : buildTypeExpression(argument);
2471 });
2472 arguments = new List<ir.Primitive>.from(arguments)
2473 ..addAll(typeArguments);
2474 }
2475 return _continueWithExpression(
2476 (k) => new ir.InvokeConstructor(type, element, selector, k,
2477 arguments));
2478 }
2479
2480 ir.Primitive buildTypeExpression(DartType type) {
2481 if (type is TypeVariableType) {
2482 return buildTypeVariableAccess(buildThis(), type);
2483 } else {
2484 assert(type is InterfaceType);
2485 // TODO(karlklose): optimization: share the type expression for variables.
asgerf 2015/03/24 12:37:21 Doesn't seem worthwhile, considering how rarely it
karlklose 2015/03/26 09:50:07 Done.
2486 List<ir.Primitive> arguments = <ir.Primitive>[];
2487 type.forEachTypeVariable((TypeVariableType variable) {
2488 ir.Primitive value = buildTypeExpression(variable);
asgerf 2015/03/24 12:37:21 It would be more clear to call buildTypeVariableAc
karlklose 2015/03/26 09:50:07 Done.
2489 arguments.add(value);
2490 });
2491 return addPrimitive(new ir.TypeExpression(type, arguments));
2492 }
2493 }
2494
2495 ir.Primitive buildTypeVariableAccess(ir.Primitive target,
2496 TypeVariableType variable) {
2497 ir.Parameter accessTypeArgumentParameter() {
2498 for (int i = 0; i < environment.length; i++) {
2499 Local local = environment.index2variable[i];
2500 if (local is TypeInformationParameter &&
2501 local.variable == variable.element) {
2502 return environment.index2value[i];
2503 }
2504 }
2505 throw 'unable to find constructor parameter for type variable $variable.';
2506 }
asgerf 2015/03/24 12:37:21 IMO a better alternative is to implement == and ha
2507
2508 if (jsState.inInitializers) {
2509 return accessTypeArgumentParameter();
2510 } else {
2511 return addPrimitive(new ir.ReadTypeVariable(variable, target));
2512 }
2513 }
2433 } 2514 }
2434 2515
2435 2516
2436 /// Location of a variable relative to a given closure. 2517 /// Location of a variable relative to a given closure.
2437 class ClosureLocation { 2518 class ClosureLocation {
2438 /// If not `null`, this location is [box].[field]. 2519 /// If not `null`, this location is [box].[field].
2439 /// The location of [box] can be obtained separately from an 2520 /// The location of [box] can be obtained separately from an
2440 /// enclosing [ClosureEnvironment] or [ClosureScope]. 2521 /// enclosing [ClosureEnvironment] or [ClosureScope].
2441 /// If `null`, then the location is [field] on the enclosing function object. 2522 /// If `null`, then the location is [field] on the enclosing function object.
2442 final BoxLocal box; 2523 final BoxLocal box;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2494 // TODO(johnniwinther): Support passing of [DartType] for the exception. 2575 // TODO(johnniwinther): Support passing of [DartType] for the exception.
2495 class CatchClauseInfo { 2576 class CatchClauseInfo {
2496 final LocalVariableElement exceptionVariable; 2577 final LocalVariableElement exceptionVariable;
2497 final LocalVariableElement stackTraceVariable; 2578 final LocalVariableElement stackTraceVariable;
2498 final SubbuildFunction buildCatchBlock; 2579 final SubbuildFunction buildCatchBlock;
2499 2580
2500 CatchClauseInfo({this.exceptionVariable, 2581 CatchClauseInfo({this.exceptionVariable,
2501 this.stackTraceVariable, 2582 this.stackTraceVariable,
2502 this.buildCatchBlock}); 2583 this.buildCatchBlock});
2503 } 2584 }
2585
2586 /// Synthetic parameter to a JavaScript factory method that takes the type
2587 /// argument given for the type variable [variable].
2588 class TypeInformationParameter implements Local {
2589 final TypeVariableElement variable;
2590 final ExecutableElement executableContext;
2591 TypeInformationParameter(this.variable, this.executableContext);
2592 String get name => variable.name;
2593 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698