blob: 617fea3170e63a20f05fde19886b524ac7571f41 [file] [log] [blame]
Florian Loitsch434bae82015-07-14 11:16:33 +02001// 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
5library dart2js.js_emitter.startup_emitter;
6
Harry Terkelsen29cf4772016-04-07 10:00:53 -07007import 'package:js_runtime/shared/embedded_names.dart'
8 show JsBuiltin, METADATA, STATIC_FUNCTION_NAME_TO_CLOSURE, TYPES;
Florian Loitsch434bae82015-07-14 11:16:33 +02009
Florian Loitsch434bae82015-07-14 11:16:33 +020010import '../../common.dart';
Harry Terkelsen29cf4772016-04-07 10:00:53 -070011import '../../compiler.dart' show Compiler;
12import '../../constants/values.dart' show ConstantValue;
13import '../../elements/elements.dart'
14 show ClassElement, Element, FieldElement, FunctionElement;
Florian Loitsch434bae82015-07-14 11:16:33 +020015import '../../js/js.dart' as js;
Harry Terkelsen29cf4772016-04-07 10:00:53 -070016import '../../js_backend/js_backend.dart' show JavaScriptBackend, Namer;
Johnni Winther254bea32016-12-16 10:10:58 +010017import '../../world.dart' show ClosedWorld;
18import '../js_emitter.dart' show CodeEmitterTask, NativeEmitter;
19import '../js_emitter.dart' as emitterTask show Emitter, EmitterFactory;
Johnni Winther1414d9b2015-10-12 09:34:02 +020020import '../model.dart';
Kevin Moore406d5e02016-08-08 14:41:50 -070021import '../program_builder/program_builder.dart' show ProgramBuilder;
Johnni Winther1414d9b2015-10-12 09:34:02 +020022import 'model_emitter.dart';
Florian Loitsch434bae82015-07-14 11:16:33 +020023
Johnni Winther254bea32016-12-16 10:10:58 +010024class 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 Loitsch434bae82015-07-14 11:16:33 +020043class 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 Loitsch5d300392015-08-03 17:46:39 +020050 Emitter(Compiler compiler, Namer namer, NativeEmitter nativeEmitter,
51 bool shouldGenerateSourceMap)
Florian Loitsch434bae82015-07-14 11:16:33 +020052 : this._compiler = compiler,
53 this.namer = namer,
Florian Loitsch5d300392015-08-03 17:46:39 +020054 _emitter = new ModelEmitter(
55 compiler, namer, nativeEmitter, shouldGenerateSourceMap);
Florian Loitsch434bae82015-07-14 11:16:33 +020056
Johnni Winther76b72032015-10-06 10:24:44 +020057 DiagnosticReporter get reporter => _compiler.reporter;
58
Florian Loitsch434bae82015-07-14 11:16:33 +020059 @override
60 int emitProgram(ProgramBuilder programBuilder) {
61 Program program = programBuilder.buildProgram();
62 return _emitter.emitProgram(program);
63 }
64
65 @override
Florian Loitsch434bae82015-07-14 11:16:33 +020066 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 Terkelsen29cf4772016-04-07 10:00:53 -0700100 return js.js('#.#',
101 [namer.globalObjectFor(element), namer.lazyInitializerName(element)]);
Florian Loitsch434bae82015-07-14 11:16:33 +0200102 }
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 Terkelsen29cf4772016-04-07 10:00:53 -0700125 js.PropertyAccess prototypeAccess(
126 ClassElement element, bool hasBeenInstantiated) {
Florian Loitsch434bae82015-07-14 11:16:33 +0200127 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 Winther62816142016-12-21 10:10:23 +0100149 typeAccess(_compiler.commonElements.objectClass));
Florian Loitsch434bae82015-07-14 11:16:33 +0200150
151 case JsBuiltin.isCheckPropertyToJsConstructorName:
152 int isPrefixLength = namer.operatorIsPrefix.length;
153 return js.js.expressionTemplateFor('#.substring($isPrefixLength)');
154
155 case JsBuiltin.isFunctionType:
Johnni Wintherda0a18d2015-10-08 13:59:16 +0200156 return _backend.rtiEncoder.templateForIsFunctionType;
Florian Loitsch434bae82015-07-14 11:16:33 +0200157
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 Wintherda0a18d2015-10-08 13:59:16 +0200165 return _backend.rtiEncoder.templateForCreateFunctionType;
Florian Loitsch434bae82015-07-14 11:16:33 +0200166
167 case JsBuiltin.isSubtype:
Harry Terkelsen29cf4772016-04-07 10:00:53 -0700168 // TODO(floitsch): move this closer to where is-check properties are
169 // built.
Florian Loitsch434bae82015-07-14 11:16:33 +0200170 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 Terkelsen29cf4772016-04-07 10:00:53 -0700182 String typesAccess = _emitter.generateEmbeddedGlobalAccessString(TYPES);
Florian Loitsch434bae82015-07-14 11:16:33 +0200183 return js.js.expressionTemplateFor("$typesAccess[#]");
184
Florian Loitsch8d6063d2015-08-03 17:48:43 +0200185 case JsBuiltin.createDartClosureFromNameOfStaticFunction:
186 String functionAccess = _emitter.generateEmbeddedGlobalAccessString(
187 STATIC_FUNCTION_NAME_TO_CLOSURE);
188 return js.js.expressionTemplateFor("$functionAccess(#)");
189
Florian Loitsch434bae82015-07-14 11:16:33 +0200190 default:
Harry Terkelsen29cf4772016-04-07 10:00:53 -0700191 reporter.internalError(
192 NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
Florian Loitsch434bae82015-07-14 11:16:33 +0200193 return null;
194 }
195 }
196
197 @override
Harry Terkelsen29cf4772016-04-07 10:00:53 -0700198 void invalidateCaches() {}
Florian Loitsch434bae82015-07-14 11:16:33 +0200199}