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_task; | 5 library dart2js.ir_builder_task; |
6 | 6 |
7 import '../closure.dart' as closure; | 7 import '../closure.dart' as closure; |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../common/names.dart' show | 9 import '../common/names.dart' show |
10 Identifiers, | 10 Identifiers, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 import '../util/util.dart'; | 52 import '../util/util.dart'; |
53 | 53 |
54 import 'package:js_runtime/shared/embedded_names.dart' | 54 import 'package:js_runtime/shared/embedded_names.dart' |
55 show JsBuiltin, JsGetName; | 55 show JsBuiltin, JsGetName; |
56 import '../constants/values.dart'; | 56 import '../constants/values.dart'; |
57 import 'type_mask_system.dart' show | 57 import 'type_mask_system.dart' show |
58 TypeMaskSystem; | 58 TypeMaskSystem; |
59 | 59 |
60 typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode); | 60 typedef void IrBuilderCallback(Element element, ir.FunctionDefinition irNode); |
61 | 61 |
| 62 class ExplicitReceiverParameter implements Local { |
| 63 final ExecutableElement executableContext; |
| 64 |
| 65 ExplicitReceiverParameter(this.executableContext); |
| 66 |
| 67 String get name => 'receiver'; |
| 68 String toString() => 'ExplicitReceiverParameter($executableContext)'; |
| 69 } |
| 70 |
62 /// This task provides the interface to build IR nodes from [ast.Node]s, which | 71 /// This task provides the interface to build IR nodes from [ast.Node]s, which |
63 /// is used from the [CpsFunctionCompiler] to generate code. | 72 /// is used from the [CpsFunctionCompiler] to generate code. |
64 /// | 73 /// |
65 /// This class is mainly there to correctly measure how long building the IR | 74 /// This class is mainly there to correctly measure how long building the IR |
66 /// takes. | 75 /// takes. |
67 class IrBuilderTask extends CompilerTask { | 76 class IrBuilderTask extends CompilerTask { |
68 final SourceInformationStrategy sourceInformationStrategy; | 77 final SourceInformationStrategy sourceInformationStrategy; |
69 | 78 |
70 String bailoutMessage = null; | 79 String bailoutMessage = null; |
71 | 80 |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 ClassElement classElement = constructor.enclosingClass.implementation; | 390 ClassElement classElement = constructor.enclosingClass.implementation; |
382 | 391 |
383 IrBuilder builder = getBuilderFor(constructor); | 392 IrBuilder builder = getBuilderFor(constructor); |
384 | 393 |
385 final bool requiresTypeInformation = | 394 final bool requiresTypeInformation = |
386 builder.program.requiresRuntimeTypesFor(classElement); | 395 builder.program.requiresRuntimeTypesFor(classElement); |
387 | 396 |
388 return withBuilder(builder, () { | 397 return withBuilder(builder, () { |
389 // Setup parameters and create a box if anything is captured. | 398 // Setup parameters and create a box if anything is captured. |
390 List<Local> parameters = <Local>[]; | 399 List<Local> parameters = <Local>[]; |
| 400 if (constructor.isGenerativeConstructor && |
| 401 backend.isNativeOrExtendsNative(classElement)) { |
| 402 parameters.add(new ExplicitReceiverParameter(constructor)); |
| 403 } |
391 constructor.functionSignature.orderedForEachParameter( | 404 constructor.functionSignature.orderedForEachParameter( |
392 (ParameterElement p) => parameters.add(p)); | 405 (ParameterElement p) => parameters.add(p)); |
393 | 406 |
394 int firstTypeArgumentParameterIndex; | 407 int firstTypeArgumentParameterIndex; |
395 | 408 |
396 // If instances of the class may need runtime type information, we add a | 409 // If instances of the class may need runtime type information, we add a |
397 // synthetic parameter for each type parameter. | 410 // synthetic parameter for each type parameter. |
398 if (requiresTypeInformation) { | 411 if (requiresTypeInformation) { |
399 firstTypeArgumentParameterIndex = parameters.length; | 412 firstTypeArgumentParameterIndex = parameters.length; |
400 classElement.typeVariables.forEach((TypeVariableType variable) { | 413 classElement.typeVariables.forEach((TypeVariableType variable) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 evaluateConstructorFieldInitializers( | 452 evaluateConstructorFieldInitializers( |
440 constructor, constructorList, fieldValues); | 453 constructor, constructorList, fieldValues); |
441 | 454 |
442 // All parameters in all constructors are now bound in the environment. | 455 // All parameters in all constructors are now bound in the environment. |
443 // BoxLocals for captured parameters are also in the environment. | 456 // BoxLocals for captured parameters are also in the environment. |
444 // The initial value of all fields are now bound in [fieldValues]. | 457 // The initial value of all fields are now bound in [fieldValues]. |
445 | 458 |
446 // --- Create the object --- | 459 // --- Create the object --- |
447 // Get the initial field values in the canonical order. | 460 // Get the initial field values in the canonical order. |
448 List<ir.Primitive> instanceArguments = <ir.Primitive>[]; | 461 List<ir.Primitive> instanceArguments = <ir.Primitive>[]; |
| 462 List<FieldElement> fields = <FieldElement>[]; |
449 classElement.forEachInstanceField((ClassElement c, FieldElement field) { | 463 classElement.forEachInstanceField((ClassElement c, FieldElement field) { |
450 ir.Primitive value = fieldValues[field]; | 464 ir.Primitive value = fieldValues[field]; |
451 if (value != null) { | 465 if (value != null) { |
| 466 fields.add(field); |
452 instanceArguments.add(value); | 467 instanceArguments.add(value); |
453 } else { | 468 } else { |
454 assert(backend.isNativeOrExtendsNative(c)); | 469 assert(backend.isNativeOrExtendsNative(c)); |
455 // Native fields are initialized elsewhere. | 470 // Native fields are initialized elsewhere. |
456 } | 471 } |
457 }, includeSuperAndInjectedMembers: true); | 472 }, includeSuperAndInjectedMembers: true); |
458 | 473 |
459 ir.Primitive instance = new ir.CreateInstance( | 474 ir.Primitive instance; |
| 475 if (constructor.isGenerativeConstructor && |
| 476 backend.isNativeOrExtendsNative(classElement)) { |
| 477 instance = irParameters.first; |
| 478 instance.type = |
| 479 new TypeMask.exact(classElement, typeMaskSystem.classWorld); |
| 480 irBuilder.addPrimitive(new ir.ReceiverCheck.nullCheck( |
| 481 instance, Selectors.toString_, null)); |
| 482 for (int i = 0; i < fields.length; i++) { |
| 483 irBuilder.addPrimitive( |
| 484 new ir.SetField(instance, fields[i], instanceArguments[i])); |
| 485 } |
| 486 } else { |
| 487 instance = new ir.CreateInstance( |
460 classElement, | 488 classElement, |
461 instanceArguments, | 489 instanceArguments, |
462 typeInformation, | 490 typeInformation, |
463 constructor.hasNode | 491 constructor.hasNode |
464 ? sourceInformationBuilder.buildCreate(constructor.node) | 492 ? sourceInformationBuilder.buildCreate(constructor.node) |
465 // TODO(johnniwinther): Provide source information for creation | 493 // TODO(johnniwinther): Provide source information for creation |
466 // through synthetic constructors. | 494 // through synthetic constructors. |
467 : null); | 495 : null); |
468 irBuilder.add(new ir.LetPrim(instance)); | 496 irBuilder.add(new ir.LetPrim(instance)); |
| 497 } |
469 | 498 |
470 // --- Call constructor bodies --- | 499 // --- Call constructor bodies --- |
471 for (ConstructorElement target in constructorList) { | 500 for (ConstructorElement target in constructorList) { |
472 ConstructorBodyElement bodyElement = getConstructorBody(target); | 501 ConstructorBodyElement bodyElement = getConstructorBody(target); |
473 if (bodyElement == null) continue; // Skip if constructor has no body. | 502 if (bodyElement == null) continue; // Skip if constructor has no body. |
474 List<ir.Primitive> bodyArguments = <ir.Primitive>[]; | 503 List<ir.Primitive> bodyArguments = <ir.Primitive>[]; |
475 for (Local param in getConstructorBodyParameters(bodyElement)) { | 504 for (Local param in getConstructorBodyParameters(bodyElement)) { |
476 bodyArguments.add(irBuilder.environment.lookup(param)); | 505 bodyArguments.add(irBuilder.environment.lookup(param)); |
477 } | 506 } |
478 Selector selector = new Selector.call(target.memberName, | 507 Selector selector = new Selector.call(target.memberName, |
(...skipping 1883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2362 if (constructor.isRedirectingFactory && !constructor.isCyclicRedirection) { | 2391 if (constructor.isRedirectingFactory && !constructor.isCyclicRedirection) { |
2363 ConstructorElement current = constructor; | 2392 ConstructorElement current = constructor; |
2364 while (current.isRedirectingFactory) { | 2393 while (current.isRedirectingFactory) { |
2365 var prefix = current.redirectionDeferredPrefix; | 2394 var prefix = current.redirectionDeferredPrefix; |
2366 if (prefix != null) buildCheckDeferredIsLoaded(prefix, send); | 2395 if (prefix != null) buildCheckDeferredIsLoaded(prefix, send); |
2367 current = current.immediateRedirectionTarget; | 2396 current = current.immediateRedirectionTarget; |
2368 } | 2397 } |
2369 } | 2398 } |
2370 | 2399 |
2371 List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit); | 2400 List<ir.Primitive> arguments = argumentsNode.nodes.mapToList(visit); |
| 2401 if (constructor.isGenerativeConstructor && |
| 2402 backend.isNativeOrExtendsNative(constructor.enclosingClass)) { |
| 2403 arguments.insert(0, irBuilder.buildNullConstant()); |
| 2404 } |
2372 // Use default values from the effective target, not the immediate target. | 2405 // Use default values from the effective target, not the immediate target. |
2373 ConstructorElement target; | 2406 ConstructorElement target; |
2374 if (constructor == compiler.symbolConstructor) { | 2407 if (constructor == compiler.symbolConstructor) { |
2375 // The Symbol constructor should perform validation of its argument | 2408 // The Symbol constructor should perform validation of its argument |
2376 // which is not expressible as a Dart const constructor. Instead, the | 2409 // which is not expressible as a Dart const constructor. Instead, the |
2377 // libraries contain a dummy const constructor implementation that | 2410 // libraries contain a dummy const constructor implementation that |
2378 // doesn't perform validation and the compiler compiles a call to | 2411 // doesn't perform validation and the compiler compiles a call to |
2379 // (non-const) Symbol.validated when it sees new Symbol(...). | 2412 // (non-const) Symbol.validated when it sees new Symbol(...). |
2380 target = compiler.symbolValidatedConstructor; | 2413 target = compiler.symbolValidatedConstructor; |
2381 } else { | 2414 } else { |
(...skipping 1842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4224 _backend.jsInteropAnalysis.hasAnonymousAnnotation(element.contextClass); | 4257 _backend.jsInteropAnalysis.hasAnonymousAnnotation(element.contextClass); |
4225 | 4258 |
4226 String getJsInteropTargetPath(FunctionElement element) { | 4259 String getJsInteropTargetPath(FunctionElement element) { |
4227 return '${_backend.namer.fixedBackendPath(element)}.' | 4260 return '${_backend.namer.fixedBackendPath(element)}.' |
4228 '${_backend.getFixedBackendName(element)}'; | 4261 '${_backend.getFixedBackendName(element)}'; |
4229 } | 4262 } |
4230 | 4263 |
4231 DartType get jsJavascriptObjectType => | 4264 DartType get jsJavascriptObjectType => |
4232 _backend.helpers.jsJavaScriptObjectClass.thisType; | 4265 _backend.helpers.jsJavaScriptObjectClass.thisType; |
4233 } | 4266 } |
OLD | NEW |