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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart

Issue 13704004: dart2js: Use js('source') instead of js['source'] to invoke JS mini-parser (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of js_backend; 5 part of js_backend;
6 6
7 class NativeEmitter { 7 class NativeEmitter {
8 8
9 CodeEmitterTask emitter; 9 CodeEmitterTask emitter;
10 CodeBuffer nativeBuffer; 10 CodeBuffer nativeBuffer;
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 // An empty native class may be omitted since the superclass methods can be 150 // An empty native class may be omitted since the superclass methods can be
151 // located via the dispatch metadata. 151 // located via the dispatch metadata.
152 // TODO(sra): Also need to check there are no subclasses that will reference 152 // TODO(sra): Also need to check there are no subclasses that will reference
153 // this class. 153 // this class.
154 // bool hasOnlyGeneratedFields = builder.properties.length == 1; 154 // bool hasOnlyGeneratedFields = builder.properties.length == 1;
155 // if (hasOnlyGeneratedFields == 1 && !hasFields) return; 155 // if (hasOnlyGeneratedFields == 1 && !hasFields) return;
156 156
157 // Define interceptor class for [classElement]. 157 // Define interceptor class for [classElement].
158 String className = backend.namer.getName(classElement); 158 String className = backend.namer.getName(classElement);
159 jsAst.Expression init = 159 jsAst.Expression init =
160 js[emitter.classesCollector][className].assign( 160 js(emitter.classesCollector)[className].assign(
161 builder.toObjectInitializer()); 161 builder.toObjectInitializer());
162 mainBuffer.write(jsAst.prettyPrint(init, compiler)); 162 mainBuffer.write(jsAst.prettyPrint(init, compiler));
163 mainBuffer.write('$N$n'); 163 mainBuffer.write('$N$n');
164 164
165 emitter.needsDefineClass = true; 165 emitter.needsDefineClass = true;
166 166
167 // Define dispatch for [classElement]. 167 // Define dispatch for [classElement].
168 String nativeTag = toNativeTag(classElement); 168 String nativeTag = toNativeTag(classElement);
169 String definer = directSubtypes[classElement] == null 169 String definer = directSubtypes[classElement] == null
170 ? defineNativeMethodsName 170 ? defineNativeMethodsName
171 : defineNativeMethodsNonleafName; 171 : defineNativeMethodsNonleafName;
172 172
173 // TODO(sra): Fix DOM generation. There is a missing proto in the picture 173 // TODO(sra): Fix DOM generation. There is a missing proto in the picture
174 // the DOM gives of the proto chain. We might need an annotation. 174 // the DOM gives of the proto chain. We might need an annotation.
175 if (nativeTag == 'HTMLElement') definer = defineNativeMethodsNonleafName; 175 if (nativeTag == 'HTMLElement') definer = defineNativeMethodsNonleafName;
176 176
177 jsAst.Expression definition = 177 jsAst.Expression definition =
178 js[definer]( 178 js(definer)(
179 [js.string(nativeTag), 179 [jsBuilder.string(nativeTag),
180 js[backend.namer.isolateAccess(classElement)]]); 180 js(backend.namer.isolateAccess(classElement))]);
181 181
182 nativeBuffer.add(jsAst.prettyPrint(definition, compiler)); 182 nativeBuffer.add(jsAst.prettyPrint(definition, compiler));
183 nativeBuffer.add('$N$n'); 183 nativeBuffer.add('$N$n');
184 184
185 classesWithDynamicDispatch.add(classElement); 185 classesWithDynamicDispatch.add(classElement);
186 } 186 }
187 187
188 void finishGenerateNativeClasses() { 188 void finishGenerateNativeClasses() {
189 // TODO(sra): Put specialized version of getNativeMethods on 189 // TODO(sra): Put specialized version of getNativeMethods on
190 // `Object.prototype` to avoid checking in `getInterceptor` and 190 // `Object.prototype` to avoid checking in `getInterceptor` and
191 // specializations. 191 // specializations.
192 192
193 // jsAst.Expression call = js[defineNativeMethodsFinishName]([]); 193 // jsAst.Expression call = js(defineNativeMethodsFinishName)([]);
194 // nativeBuffer.add(jsAst.prettyPrint(call, compiler)); 194 // nativeBuffer.add(jsAst.prettyPrint(call, compiler));
195 // nativeBuffer.add('$N$n'); 195 // nativeBuffer.add('$N$n');
196 } 196 }
197 197
198 List<ClassElement> getDirectSubclasses(ClassElement cls) { 198 List<ClassElement> getDirectSubclasses(ClassElement cls) {
199 List<ClassElement> result = directSubtypes[cls]; 199 List<ClassElement> result = directSubtypes[cls];
200 return result == null ? const<ClassElement>[] : result; 200 return result == null ? const<ClassElement>[] : result;
201 } 201 }
202 202
203 void potentiallyConvertDartClosuresToJs( 203 void potentiallyConvertDartClosuresToJs(
(...skipping 13 matching lines...) Expand all
217 for (jsAst.Parameter stubParameter in stubParameters) { 217 for (jsAst.Parameter stubParameter in stubParameters) {
218 if (stubParameter.name == name) { 218 if (stubParameter.name == name) {
219 DartType type = parameter.computeType(compiler).unalias(compiler); 219 DartType type = parameter.computeType(compiler).unalias(compiler);
220 if (type is FunctionType) { 220 if (type is FunctionType) {
221 // The parameter type is a function type either directly or through 221 // The parameter type is a function type either directly or through
222 // typedef(s). 222 // typedef(s).
223 int arity = type.computeArity(); 223 int arity = type.computeArity();
224 224
225 statements.add( 225 statements.add(
226 new jsAst.ExpressionStatement( 226 new jsAst.ExpressionStatement(
227 js.assign( 227 jsBuilder.assign(
228 js[name], 228 js(name),
229 js[closureConverter]( 229 js(closureConverter)(
230 [js[name], 230 [js(name),
231 new jsAst.LiteralNumber('$arity')])))); 231 new jsAst.LiteralNumber('$arity')]))));
232 break; 232 break;
233 } 233 }
234 } 234 }
235 } 235 }
236 }); 236 });
237 } 237 }
238 238
239 List<jsAst.Statement> generateParameterStubStatements( 239 List<jsAst.Statement> generateParameterStubStatements(
240 Element member, 240 Element member,
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 tagDefns[tag] = new jsAst.VariableUse(varName); 372 tagDefns[tag] = new jsAst.VariableUse(varName);
373 expressions.add(new jsAst.VariableUse(varName)); 373 expressions.add(new jsAst.VariableUse(varName));
374 } 374 }
375 } 375 }
376 } 376 }
377 } 377 }
378 walk(classElement); 378 walk(classElement);
379 379
380 if (!subtags.isEmpty) { 380 if (!subtags.isEmpty) {
381 subtags.sort(); 381 subtags.sort();
382 expressions.add(js.string(subtags.join('|'))); 382 expressions.add(jsBuilder.string(subtags.join('|')));
383 } 383 }
384 jsAst.Expression expression; 384 jsAst.Expression expression;
385 if (expressions.length == 1) { 385 if (expressions.length == 1) {
386 expression = expressions[0]; 386 expression = expressions[0];
387 } else { 387 } else {
388 jsAst.Expression array = new jsAst.ArrayInitializer.from(expressions); 388 jsAst.Expression array = new jsAst.ArrayInitializer.from(expressions);
389 expression = array['join']([js.string('|')]); 389 expression = array['join']([jsBuilder.string('|')]);
390 } 390 }
391 return expression; 391 return expression;
392 } 392 }
393 393
394 for (final ClassElement classElement in preorderDispatchClasses) { 394 for (final ClassElement classElement in preorderDispatchClasses) {
395 tagDefns[classElement] = makeExpression(classElement); 395 tagDefns[classElement] = makeExpression(classElement);
396 } 396 }
397 397
398 // Write out a thunk that builds the metadata. 398 // Write out a thunk that builds the metadata.
399 if (!tagDefns.isEmpty) { 399 if (!tagDefns.isEmpty) {
(...skipping 14 matching lines...) Expand all
414 } 414 }
415 415
416 // [table] is a list of lists, each inner list of the form: 416 // [table] is a list of lists, each inner list of the form:
417 // [dynamic-dispatch-tag, tags-of-classes-implementing-dispatch-tag] 417 // [dynamic-dispatch-tag, tags-of-classes-implementing-dispatch-tag]
418 // E.g. 418 // E.g.
419 // [['Node', 'Text|HTMLElement|HTMLDivElement|...'], ...] 419 // [['Node', 'Text|HTMLElement|HTMLDivElement|...'], ...]
420 jsAst.Expression table = 420 jsAst.Expression table =
421 new jsAst.ArrayInitializer.from( 421 new jsAst.ArrayInitializer.from(
422 preorderDispatchClasses.map((cls) => 422 preorderDispatchClasses.map((cls) =>
423 new jsAst.ArrayInitializer.from([ 423 new jsAst.ArrayInitializer.from([
424 js.string(toNativeTag(cls)), 424 jsBuilder.string(toNativeTag(cls)),
425 tagDefns[cls]]))); 425 tagDefns[cls]])));
426 426
427 // $.dynamicSetMetadata(table); 427 // $.dynamicSetMetadata(table);
428 statements.add( 428 statements.add(
429 new jsAst.ExpressionStatement( 429 new jsAst.ExpressionStatement(
430 new jsAst.Call( 430 new jsAst.Call(
431 new jsAst.VariableUse(dynamicSetMetadataName), 431 new jsAst.VariableUse(dynamicSetMetadataName),
432 [table]))); 432 [table])));
433 433
434 // (function(){statements})(); 434 // (function(){statements})();
(...skipping 30 matching lines...) Expand all
465 if (!element.isClass()) return false; 465 if (!element.isClass()) return false;
466 ClassElement cls = element; 466 ClassElement cls = element;
467 if (cls.isNative()) return true; 467 if (cls.isNative()) return true;
468 return isSupertypeOfNativeClass(element); 468 return isSupertypeOfNativeClass(element);
469 } 469 }
470 470
471 void assembleCode(CodeBuffer targetBuffer) { 471 void assembleCode(CodeBuffer targetBuffer) {
472 List<jsAst.Property> objectProperties = <jsAst.Property>[]; 472 List<jsAst.Property> objectProperties = <jsAst.Property>[];
473 473
474 void addProperty(String name, jsAst.Expression value) { 474 void addProperty(String name, jsAst.Expression value) {
475 objectProperties.add(new jsAst.Property(js.string(name), value)); 475 objectProperties.add(new jsAst.Property(jsBuilder.string(name), value));
476 } 476 }
477 477
478 // Because of native classes, we have to generate some is checks 478 // Because of native classes, we have to generate some is checks
479 // by calling a method, instead of accessing a property. So we 479 // by calling a method, instead of accessing a property. So we
480 // attach to the JS Object prototype these methods that return 480 // attach to the JS Object prototype these methods that return
481 // false, and will be overridden by subclasses when they have to 481 // false, and will be overridden by subclasses when they have to
482 // return true. 482 // return true.
483 void emitIsChecks() { 483 void emitIsChecks() {
484 for (ClassElement element in 484 for (ClassElement element in
485 Elements.sortedByPosition(emitter.checkedClasses)) { 485 Elements.sortedByPosition(emitter.checkedClasses)) {
486 if (!requiresNativeIsCheck(element)) continue; 486 if (!requiresNativeIsCheck(element)) continue;
487 if (element.isObject(compiler)) continue; 487 if (element.isObject(compiler)) continue;
488 // Add function for the is-test. 488 // Add function for the is-test.
489 String name = backend.namer.operatorIs(element); 489 String name = backend.namer.operatorIs(element);
490 addProperty(name, 490 addProperty(name,
491 js.fun([], js.return_(js['false']))); 491 jsBuilder.fun([], jsBuilder.return_(js('false'))));
492 // Add a function for the (trivial) substitution. 492 // Add a function for the (trivial) substitution.
493 addProperty(backend.namer.substitutionName(element), 493 addProperty(backend.namer.substitutionName(element),
494 js.fun([], js.return_(js['null']))); 494 jsBuilder.fun([], jsBuilder.return_(js('null'))));
495 } 495 }
496 } 496 }
497 emitIsChecks(); 497 emitIsChecks();
498 498
499 jsAst.Expression makeCallOnThis(String functionName) { 499 jsAst.Expression makeCallOnThis(String functionName) {
500 // Because we know the function is intercepted, we need an extra 500 // Because we know the function is intercepted, we need an extra
501 // parameter. 501 // parameter.
502 return js.fun(['_'], js.return_(js['$functionName(this)'])); 502 return jsBuilder.fun(['_'], jsBuilder.return_(js('$functionName(this)')));
503 } 503 }
504 504
505 if (!nativeClasses.isEmpty) { 505 if (!nativeClasses.isEmpty) {
506 emitDynamicDispatchMetadata(); 506 emitDynamicDispatchMetadata();
507 507
508 // In order to have the toString method on every native class, 508 // In order to have the toString method on every native class,
509 // we must patch the JS Object prototype with a helper method. 509 // we must patch the JS Object prototype with a helper method.
510 String toStringName = backend.namer.publicInstanceMethodNameByArity( 510 String toStringName = backend.namer.publicInstanceMethodNameByArity(
511 const SourceString('toString'), 0); 511 const SourceString('toString'), 0);
512 addProperty(toStringName, makeCallOnThis(toStringHelperName)); 512 addProperty(toStringName, makeCallOnThis(toStringHelperName));
513 513
514 // Same as above, but for hashCode. 514 // Same as above, but for hashCode.
515 String hashCodeName = 515 String hashCodeName =
516 backend.namer.publicGetterName(const SourceString('hashCode')); 516 backend.namer.publicGetterName(const SourceString('hashCode'));
517 addProperty(hashCodeName, makeCallOnThis(hashCodeHelperName)); 517 addProperty(hashCodeName, makeCallOnThis(hashCodeHelperName));
518 518
519 // Same as above, but for operator==. 519 // Same as above, but for operator==.
520 String equalsName = backend.namer.publicInstanceMethodNameByArity( 520 String equalsName = backend.namer.publicInstanceMethodNameByArity(
521 const SourceString('=='), 1); 521 const SourceString('=='), 1);
522 // Because we know the function is intercepted, we need an extra 522 // Because we know the function is intercepted, we need an extra
523 // parameter. 523 // parameter.
524 addProperty(equalsName, js.fun(['_', 'a'], 524 addProperty(equalsName, jsBuilder.fun(['_', 'a'],
525 js.return_(js['this === a']))); 525 jsBuilder.return_(js('this === a'))));
526 526
527 // If the native emitter has been asked to take care of the 527 // If the native emitter has been asked to take care of the
528 // noSuchMethod handlers, we do that now. 528 // noSuchMethod handlers, we do that now.
529 if (handleNoSuchMethod) { 529 if (handleNoSuchMethod) {
530 emitter.emitNoSuchMethodHandlers(addProperty); 530 emitter.emitNoSuchMethodHandlers(addProperty);
531 } 531 }
532 } 532 }
533 533
534 // If we have any properties to add to Object.prototype, we run 534 // If we have any properties to add to Object.prototype, we run
535 // through them and add them using defineProperty. 535 // through them and add them using defineProperty.
536 if (!objectProperties.isEmpty) { 536 if (!objectProperties.isEmpty) {
537 jsAst.Expression init = 537 jsAst.Expression init =
538 js.fun(['table'], 538 jsBuilder.fun(['table'],
539 new jsAst.ForIn( 539 new jsAst.ForIn(
540 new jsAst.VariableDeclarationList( 540 new jsAst.VariableDeclarationList(
541 [new jsAst.VariableInitialization( 541 [new jsAst.VariableInitialization(
542 new jsAst.VariableDeclaration('key'), 542 new jsAst.VariableDeclaration('key'),
543 null)]), 543 null)]),
544 js['table'], 544 js('table'),
545 new jsAst.ExpressionStatement( 545 new jsAst.ExpressionStatement(
546 js['$defPropName(Object.prototype, key, table[key])'])))( 546 js('$defPropName(Object.prototype, key, table[key])'))))(
547 new jsAst.ObjectInitializer(objectProperties)); 547 new jsAst.ObjectInitializer(objectProperties));
548 548
549 if (emitter.compiler.enableMinification) targetBuffer.add(';'); 549 if (emitter.compiler.enableMinification) targetBuffer.add(';');
550 targetBuffer.add(jsAst.prettyPrint( 550 targetBuffer.add(jsAst.prettyPrint(
551 new jsAst.ExpressionStatement(init), compiler)); 551 new jsAst.ExpressionStatement(init), compiler));
552 targetBuffer.add('\n'); 552 targetBuffer.add('\n');
553 } 553 }
554 554
555 targetBuffer.add(nativeBuffer); 555 targetBuffer.add(nativeBuffer);
556 targetBuffer.add('\n'); 556 targetBuffer.add('\n');
557 } 557 }
558 } 558 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698