Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 | |
| 5 | library dart2js.js_emitter.startup_emitter; |
| 6 | |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 7 | import 'package:js_runtime/shared/embedded_names.dart' |
| 8 | show JsBuiltin, METADATA, STATIC_FUNCTION_NAME_TO_CLOSURE, TYPES; |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 9 | |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 10 | import '../../common.dart'; |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 11 | import '../../compiler.dart' show Compiler; |
| 12 | import '../../constants/values.dart' show ConstantValue; |
| 13 | import '../../elements/elements.dart' |
| 14 | show ClassElement, Element, FieldElement, FunctionElement; |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 15 | import '../../js/js.dart' as js; |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 16 | import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer; |
Johnni Winther | 254bea3 | 2016-12-16 10:10:58 +0100 | [diff] [blame] | 17 | import '../../world.dart' show ClosedWorld; |
| 18 | import '../js_emitter.dart' show CodeEmitterTask, NativeEmitter; |
| 19 | import '../js_emitter.dart' as emitterTask show Emitter, EmitterFactory; |
Johnni Winther | 1414d9b | 2015-10-12 09:34:02 +0200 | [diff] [blame] | 20 | import '../model.dart'; |
Kevin Moore | 406d5e0 | 2016-08-08 14:41:50 -0700 | [diff] [blame] | 21 | import '../program_builder/program_builder.dart' show ProgramBuilder; |
Johnni Winther | 1414d9b | 2015-10-12 09:34:02 +0200 | [diff] [blame] | 22 | import 'model_emitter.dart'; |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 23 | |
Johnni Winther | 254bea3 | 2016-12-16 10:10:58 +0100 | [diff] [blame] | 24 | class EmitterFactory implements emitterTask.EmitterFactory { |
| 25 | final bool generateSourceMap; |
| 26 | |
| 27 | EmitterFactory({this.generateSourceMap}); |
| 28 | |
| 29 | @override |
| 30 | String get patchVersion => "startup"; |
| 31 | |
| 32 | @override |
| 33 | bool get supportsReflection => false; |
| 34 | |
| 35 | @override |
| 36 | Emitter createEmitter( |
| 37 | CodeEmitterTask task, Namer namer, ClosedWorld closedWorld) { |
| 38 | return new Emitter( |
| 39 | task.compiler, namer, task.nativeEmitter, generateSourceMap); |
| 40 | } |
| 41 | } |
| 42 | |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 43 | class Emitter implements emitterTask.Emitter { |
| 44 | final Compiler _compiler; |
| 45 | final Namer namer; |
| 46 | final ModelEmitter _emitter; |
| 47 | |
| 48 | JavaScriptBackend get _backend => _compiler.backend; |
| 49 | |
Florian Loitsch | 5d30039 | 2015-08-03 17:46:39 +0200 | [diff] [blame] | 50 | Emitter(Compiler compiler, Namer namer, NativeEmitter nativeEmitter, |
| 51 | bool shouldGenerateSourceMap) |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 52 | : this._compiler = compiler, |
| 53 | this.namer = namer, |
Florian Loitsch | 5d30039 | 2015-08-03 17:46:39 +0200 | [diff] [blame] | 54 | _emitter = new ModelEmitter( |
| 55 | compiler, namer, nativeEmitter, shouldGenerateSourceMap); |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 56 | |
Johnni Winther | 76b7203 | 2015-10-06 10:24:44 +0200 | [diff] [blame] | 57 | DiagnosticReporter get reporter => _compiler.reporter; |
| 58 | |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 59 | @override |
| 60 | int emitProgram(ProgramBuilder programBuilder) { |
| 61 | Program program = programBuilder.buildProgram(); |
| 62 | return _emitter.emitProgram(program); |
| 63 | } |
| 64 | |
| 65 | @override |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 66 | bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
| 67 | return _emitter.isConstantInlinedOrAlreadyEmitted(constant); |
| 68 | } |
| 69 | |
| 70 | @override |
| 71 | int compareConstants(ConstantValue a, ConstantValue b) { |
| 72 | return _emitter.compareConstants(a, b); |
| 73 | } |
| 74 | |
| 75 | @override |
| 76 | js.Expression constantReference(ConstantValue value) { |
| 77 | return _emitter.generateConstantReference(value); |
| 78 | } |
| 79 | |
| 80 | @override |
| 81 | js.Expression generateEmbeddedGlobalAccess(String global) { |
| 82 | return _emitter.generateEmbeddedGlobalAccess(global); |
| 83 | } |
| 84 | |
| 85 | @override |
| 86 | // TODO(herhut): Use a single shared function. |
| 87 | js.Expression generateFunctionThatReturnsNull() { |
| 88 | return js.js('function() {}'); |
| 89 | } |
| 90 | |
| 91 | js.PropertyAccess _globalPropertyAccess(Element element) { |
| 92 | js.Name name = namer.globalPropertyName(element); |
| 93 | js.PropertyAccess pa = new js.PropertyAccess( |
| 94 | new js.VariableUse(namer.globalObjectFor(element)), name); |
| 95 | return pa; |
| 96 | } |
| 97 | |
| 98 | @override |
| 99 | js.Expression isolateLazyInitializerAccess(FieldElement element) { |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 100 | return js.js('#.#', |
| 101 | [namer.globalObjectFor(element), namer.lazyInitializerName(element)]); |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 102 | } |
| 103 | |
| 104 | @override |
| 105 | js.Expression isolateStaticClosureAccess(FunctionElement element) { |
| 106 | return _emitter.generateStaticClosureAccess(element); |
| 107 | } |
| 108 | |
| 109 | @override |
| 110 | js.PropertyAccess staticFieldAccess(FieldElement element) { |
| 111 | return _globalPropertyAccess(element); |
| 112 | } |
| 113 | |
| 114 | @override |
| 115 | js.PropertyAccess staticFunctionAccess(FunctionElement element) { |
| 116 | return _globalPropertyAccess(element); |
| 117 | } |
| 118 | |
| 119 | @override |
| 120 | js.PropertyAccess constructorAccess(ClassElement element) { |
| 121 | return _globalPropertyAccess(element); |
| 122 | } |
| 123 | |
| 124 | @override |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 125 | js.PropertyAccess prototypeAccess( |
| 126 | ClassElement element, bool hasBeenInstantiated) { |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 127 | js.Expression constructor = |
| 128 | hasBeenInstantiated ? constructorAccess(element) : typeAccess(element); |
| 129 | return js.js('#.prototype', constructor); |
| 130 | } |
| 131 | |
| 132 | @override |
| 133 | js.Expression interceptorClassAccess(ClassElement element) { |
| 134 | return _globalPropertyAccess(element); |
| 135 | } |
| 136 | |
| 137 | @override |
| 138 | js.Expression typeAccess(Element element) { |
| 139 | return _globalPropertyAccess(element); |
| 140 | } |
| 141 | |
| 142 | @override |
| 143 | js.Template templateForBuiltin(JsBuiltin builtin) { |
| 144 | String typeNameProperty = ModelEmitter.typeNameProperty; |
| 145 | |
| 146 | switch (builtin) { |
| 147 | case JsBuiltin.dartObjectConstructor: |
| 148 | return js.js.expressionTemplateYielding( |
Johnni Winther | 6281614 | 2016-12-21 10:10:23 +0100 | [diff] [blame] | 149 | typeAccess(_compiler.commonElements.objectClass)); |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 150 | |
| 151 | case JsBuiltin.isCheckPropertyToJsConstructorName: |
| 152 | int isPrefixLength = namer.operatorIsPrefix.length; |
| 153 | return js.js.expressionTemplateFor('#.substring($isPrefixLength)'); |
| 154 | |
| 155 | case JsBuiltin.isFunctionType: |
Johnni Winther | da0a18d | 2015-10-08 13:59:16 +0200 | [diff] [blame] | 156 | return _backend.rtiEncoder.templateForIsFunctionType; |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 157 | |
| 158 | case JsBuiltin.rawRtiToJsConstructorName: |
| 159 | return js.js.expressionTemplateFor("#.$typeNameProperty"); |
| 160 | |
| 161 | case JsBuiltin.rawRuntimeType: |
| 162 | return js.js.expressionTemplateFor("#.constructor"); |
| 163 | |
| 164 | case JsBuiltin.createFunctionTypeRti: |
Johnni Winther | da0a18d | 2015-10-08 13:59:16 +0200 | [diff] [blame] | 165 | return _backend.rtiEncoder.templateForCreateFunctionType; |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 166 | |
| 167 | case JsBuiltin.isSubtype: |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 168 | // TODO(floitsch): move this closer to where is-check properties are |
| 169 | // built. |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 170 | String isPrefix = namer.operatorIsPrefix; |
| 171 | return js.js.expressionTemplateFor("('$isPrefix' + #) in #.prototype"); |
| 172 | |
| 173 | case JsBuiltin.isGivenTypeRti: |
| 174 | return js.js.expressionTemplateFor('#.$typeNameProperty === #'); |
| 175 | |
| 176 | case JsBuiltin.getMetadata: |
| 177 | String metadataAccess = |
| 178 | _emitter.generateEmbeddedGlobalAccessString(METADATA); |
| 179 | return js.js.expressionTemplateFor("$metadataAccess[#]"); |
| 180 | |
| 181 | case JsBuiltin.getType: |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 182 | String typesAccess = _emitter.generateEmbeddedGlobalAccessString(TYPES); |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 183 | return js.js.expressionTemplateFor("$typesAccess[#]"); |
| 184 | |
Florian Loitsch | 8d6063d | 2015-08-03 17:48:43 +0200 | [diff] [blame] | 185 | case JsBuiltin.createDartClosureFromNameOfStaticFunction: |
| 186 | String functionAccess = _emitter.generateEmbeddedGlobalAccessString( |
| 187 | STATIC_FUNCTION_NAME_TO_CLOSURE); |
| 188 | return js.js.expressionTemplateFor("$functionAccess(#)"); |
| 189 | |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 190 | default: |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 191 | reporter.internalError( |
| 192 | NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin"); |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 193 | return null; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | @override |
Harry Terkelsen | 29cf477 | 2016-04-07 10:00:53 -0700 | [diff] [blame] | 198 | void invalidateCaches() {} |
Florian Loitsch | 434bae8 | 2015-07-14 11:16:33 +0200 | [diff] [blame] | 199 | } |