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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart

Issue 246633006: Revert "JS templates" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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) 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 part of dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 /// This class should morph into something that makes it easy to build 7 /// This class should morph into something that makes it easy to build
8 /// JavaScript representations of libraries, class-sides, and instance-sides. 8 /// JavaScript representations of libraries, class-sides, and instance-sides.
9 /// Initially, it is just a placeholder for code that is moved from 9 /// Initially, it is just a placeholder for code that is moved from
10 /// [CodeEmitterTask]. 10 /// [CodeEmitterTask].
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); 64 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount);
65 // The arguments that will be passed to the real method. 65 // The arguments that will be passed to the real method.
66 List<jsAst.Expression> argumentsBuffer = 66 List<jsAst.Expression> argumentsBuffer =
67 new List<jsAst.Expression>( 67 new List<jsAst.Expression>(
68 parameters.parameterCount + extraArgumentCount); 68 parameters.parameterCount + extraArgumentCount);
69 69
70 int count = 0; 70 int count = 0;
71 if (isInterceptedMethod) { 71 if (isInterceptedMethod) {
72 count++; 72 count++;
73 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); 73 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName);
74 argumentsBuffer[0] = js('#', receiverArgumentName); 74 argumentsBuffer[0] = js(receiverArgumentName);
75 task.interceptorEmitter.interceptorInvocationNames.add(invocationName); 75 task.interceptorEmitter.interceptorInvocationNames.add(invocationName);
76 } 76 }
77 77
78 int optionalParameterStart = positionalArgumentCount + extraArgumentCount; 78 int optionalParameterStart = positionalArgumentCount + extraArgumentCount;
79 // Includes extra receiver argument when using interceptor convention 79 // Includes extra receiver argument when using interceptor convention
80 int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1; 80 int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1;
81 81
82 TreeElements elements = 82 TreeElements elements =
83 compiler.enqueuer.resolution.getCachedElements(member); 83 compiler.enqueuer.resolution.getCachedElements(member);
84 84
85 int parameterIndex = 0; 85 int parameterIndex = 0;
86 parameters.orderedForEachParameter((Element element) { 86 parameters.orderedForEachParameter((Element element) {
87 String jsName = backend.namer.safeName(element.name); 87 String jsName = backend.namer.safeName(element.name);
88 assert(jsName != receiverArgumentName); 88 assert(jsName != receiverArgumentName);
89 if (count < optionalParameterStart) { 89 if (count < optionalParameterStart) {
90 parametersBuffer[count] = new jsAst.Parameter(jsName); 90 parametersBuffer[count] = new jsAst.Parameter(jsName);
91 argumentsBuffer[count] = js('#', jsName); 91 argumentsBuffer[count] = js(jsName);
92 } else { 92 } else {
93 int index = names.indexOf(element.name); 93 int index = names.indexOf(element.name);
94 if (index != -1) { 94 if (index != -1) {
95 indexOfLastOptionalArgumentInParameters = count; 95 indexOfLastOptionalArgumentInParameters = count;
96 // The order of the named arguments is not the same as the 96 // The order of the named arguments is not the same as the
97 // one in the real method (which is in Dart source order). 97 // one in the real method (which is in Dart source order).
98 argumentsBuffer[count] = js('#', jsName); 98 argumentsBuffer[count] = js(jsName);
99 parametersBuffer[optionalParameterStart + index] = 99 parametersBuffer[optionalParameterStart + index] =
100 new jsAst.Parameter(jsName); 100 new jsAst.Parameter(jsName);
101 } else { 101 } else {
102 Constant value = handler.getConstantForVariable(element); 102 Constant value = handler.getConstantForVariable(element);
103 if (value == null) { 103 if (value == null) {
104 argumentsBuffer[count] = task.constantReference(new NullConstant()); 104 argumentsBuffer[count] = task.constantReference(new NullConstant());
105 } else { 105 } else {
106 if (!value.isNull) { 106 if (!value.isNull) {
107 // If the value is the null constant, we should not pass it 107 // If the value is the null constant, we should not pass it
108 // down to the native method. 108 // down to the native method.
109 indexOfLastOptionalArgumentInParameters = count; 109 indexOfLastOptionalArgumentInParameters = count;
110 } 110 }
111 argumentsBuffer[count] = task.constantReference(value); 111 argumentsBuffer[count] = task.constantReference(value);
112 } 112 }
113 } 113 }
114 } 114 }
115 count++; 115 count++;
116 }); 116 });
117 117
118 var body; // List or jsAst.Statement. 118 List body;
119 if (member.hasFixedBackendName()) { 119 if (member.hasFixedBackendName()) {
120 body = task.nativeEmitter.generateParameterStubStatements( 120 body = task.nativeEmitter.generateParameterStubStatements(
121 member, isInterceptedMethod, invocationName, 121 member, isInterceptedMethod, invocationName,
122 parametersBuffer, argumentsBuffer, 122 parametersBuffer, argumentsBuffer,
123 indexOfLastOptionalArgumentInParameters); 123 indexOfLastOptionalArgumentInParameters);
124 } else if (member.isInstanceMember()) { 124 } else if (member.isInstanceMember()) {
125 if (needsSuperGetter(member)) { 125 if (needsSuperGetter(member)) {
126 ClassElement superClass = member.getEnclosingClass(); 126 ClassElement superClass = member.getEnclosingClass();
127 String methodName = namer.getNameOfInstanceMember(member); 127 String methodName = namer.getNameOfInstanceMember(member);
128 // When redirecting, we must ensure that we don't end up in a subclass. 128 // When redirecting, we must ensure that we don't end up in a subclass.
129 // We thus can't just invoke `this.foo$1.call(filledInArguments)`. 129 // We thus can't just invoke `this.foo$1.call(filledInArguments)`.
130 // Instead we need to call the statically resolved target. 130 // Instead we need to call the statically resolved target.
131 // `<class>.prototype.bar$1.call(this, argument0, ...)`. 131 // `<class>.prototype.bar$1.call(this, argument0, ...)`.
132 body = js.statement( 132 body = [js.return_(
133 'return #.prototype.#.call(this, #);', 133 backend.namer.elementAccess(superClass)['prototype'][methodName]
134 [backend.namer.elementAccess(superClass), methodName, 134 ["call"](["this"]..addAll(argumentsBuffer)))];
135 argumentsBuffer]);
136 } else { 135 } else {
137 body = js.statement( 136 body = [js.return_(
138 'return this.#(#);', 137 js('this')
139 [namer.getNameOfInstanceMember(member), argumentsBuffer]); 138 [namer.getNameOfInstanceMember(member)](argumentsBuffer))];
140 } 139 }
141 } else { 140 } else {
142 body = js.statement('return #(#)', 141 body = [js.return_(namer.elementAccess(member)(argumentsBuffer))];
143 [namer.elementAccess(member), argumentsBuffer]);
144 } 142 }
145 143
146 jsAst.Fun function = js('function(#) { #; }', [parametersBuffer, body]); 144 jsAst.Fun function = js.fun(parametersBuffer, body);
147 145
148 addStub(selector, function); 146 addStub(selector, function);
149 } 147 }
150 148
151 void addParameterStubs(FunctionElement member, AddStubFunction defineStub, 149 void addParameterStubs(FunctionElement member, AddStubFunction defineStub,
152 [bool canTearOff = false]) { 150 [bool canTearOff = false]) {
153 if (member.enclosingElement.isClosure()) { 151 if (member.enclosingElement.isClosure()) {
154 ClosureClassElement cls = member.enclosingElement; 152 ClosureClassElement cls = member.enclosingElement;
155 if (cls.supertype.element == compiler.boundClosureClass) { 153 if (cls.supertype.element == compiler.boundClosureClass) {
156 compiler.internalError(cls.methodElement, 'Bound closure1.'); 154 compiler.internalError(cls.methodElement, 'Bound closure1.');
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 backend.isInterceptorClass(member.getEnclosingClass()); 260 backend.isInterceptorClass(member.getEnclosingClass());
263 261
264 const String receiverArgumentName = r'$receiver'; 262 const String receiverArgumentName = r'$receiver';
265 263
266 jsAst.Expression buildGetter() { 264 jsAst.Expression buildGetter() {
267 jsAst.Expression receiver = 265 jsAst.Expression receiver =
268 js(isInterceptorClass ? receiverArgumentName : 'this'); 266 js(isInterceptorClass ? receiverArgumentName : 'this');
269 if (member.isGetter()) { 267 if (member.isGetter()) {
270 String getterName = namer.getterName(member); 268 String getterName = namer.getterName(member);
271 if (isInterceptedMethod) { 269 if (isInterceptedMethod) {
272 return js('this.#(#)', [getterName, receiver]); 270 return js('this')[getterName](<jsAst.Expression>[receiver]);
273 } 271 }
274 return js('#.#()', [receiver, getterName]); 272 return receiver[getterName](<jsAst.Expression>[]);
275 } else { 273 } else {
276 String fieldName = namer.instanceFieldPropertyName(member); 274 String fieldName = namer.instanceFieldPropertyName(member);
277 return js('#.#', [receiver, fieldName]); 275 return receiver[fieldName];
278 } 276 }
279 } 277 }
280 278
281 // Two selectors may match but differ only in type. To avoid generating 279 // Two selectors may match but differ only in type. To avoid generating
282 // identical stubs for each we track untyped selectors which already have 280 // identical stubs for each we track untyped selectors which already have
283 // stubs. 281 // stubs.
284 Set<Selector> generatedSelectors = new Set<Selector>(); 282 Set<Selector> generatedSelectors = new Set<Selector>();
285 for (Selector selector in selectors) { 283 for (Selector selector in selectors) {
286 if (selector.applies(member, compiler)) { 284 if (selector.applies(member, compiler)) {
287 selector = selector.asUntyped; 285 selector = selector.asUntyped;
288 if (generatedSelectors.contains(selector)) continue; 286 if (generatedSelectors.contains(selector)) continue;
289 generatedSelectors.add(selector); 287 generatedSelectors.add(selector);
290 288
291 String invocationName = namer.invocationName(selector); 289 String invocationName = namer.invocationName(selector);
292 Selector callSelector = new Selector.callClosureFrom(selector); 290 Selector callSelector = new Selector.callClosureFrom(selector);
293 String closureCallName = namer.invocationName(callSelector); 291 String closureCallName = namer.invocationName(callSelector);
294 292
295 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; 293 List<jsAst.Parameter> parameters = <jsAst.Parameter>[];
296 List<jsAst.Expression> arguments = <jsAst.Expression>[]; 294 List<jsAst.Expression> arguments = <jsAst.Expression>[];
297 if (isInterceptedMethod) { 295 if (isInterceptedMethod) {
298 parameters.add(new jsAst.Parameter(receiverArgumentName)); 296 parameters.add(new jsAst.Parameter(receiverArgumentName));
299 } 297 }
300 298
301 for (int i = 0; i < selector.argumentCount; i++) { 299 for (int i = 0; i < selector.argumentCount; i++) {
302 String name = 'arg$i'; 300 String name = 'arg$i';
303 parameters.add(new jsAst.Parameter(name)); 301 parameters.add(new jsAst.Parameter(name));
304 arguments.add(js('#', name)); 302 arguments.add(js(name));
305 } 303 }
306 304
307 jsAst.Fun function = js( 305 jsAst.Fun function = js.fun(
308 'function(#) { return #.#(#); }', 306 parameters,
309 [ parameters, buildGetter(), closureCallName, arguments]); 307 js.return_(buildGetter()[closureCallName](arguments)));
310 308
311 addProperty(invocationName, function); 309 addProperty(invocationName, function);
312 } 310 }
313 } 311 }
314 } 312 }
315 313
316 /** 314 /**
317 * Documentation wanted -- johnniwinther 315 * Documentation wanted -- johnniwinther
318 * 316 *
319 * Invariant: [member] must be a declaration element. 317 * Invariant: [member] must be a declaration element.
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 // N+4. First default argument. 417 // N+4. First default argument.
420 // ... 418 // ...
421 // O. First parameter name (if needed for reflection or Function.apply). 419 // O. First parameter name (if needed for reflection or Function.apply).
422 // ... 420 // ...
423 // P. Unmangled name (if reflectable). 421 // P. Unmangled name (if reflectable).
424 // P+1. First metadata (if reflectable). 422 // P+1. First metadata (if reflectable).
425 // ... 423 // ...
426 // TODO(ahe): Consider one of the parameter counts can be replaced by the 424 // TODO(ahe): Consider one of the parameter counts can be replaced by the
427 // length property of the JavaScript function object. 425 // length property of the JavaScript function object.
428 426
429 List<jsAst.Expression> expressions = <jsAst.Expression>[]; 427 List expressions = [];
430 428
431 String callSelectorString = 'null'; 429 String callSelectorString = 'null';
432 if (member.isFunction()) { 430 if (member.isFunction()) {
433 Selector callSelector = 431 Selector callSelector =
434 new Selector.fromElement(member, compiler).toCallSelector(); 432 new Selector.fromElement(member, compiler).toCallSelector();
435 callSelectorString = '"${namer.invocationName(callSelector)}"'; 433 callSelectorString = '"${namer.invocationName(callSelector)}"';
436 } 434 }
437 435
438 // On [requiredParameterCount], the lower bit is set if this method can be 436 // On [requiredParameterCount], the lower bit is set if this method can be
439 // called reflectively. 437 // called reflectively.
440 int requiredParameterCount = parameters.requiredParameterCount << 1; 438 int requiredParameterCount = parameters.requiredParameterCount << 1;
441 if (member.isAccessor()) requiredParameterCount++; 439 if (member.isAccessor()) requiredParameterCount++;
442 440
443 int optionalParameterCount = parameters.optionalParameterCount << 1; 441 int optionalParameterCount = parameters.optionalParameterCount << 1;
444 if (parameters.optionalParametersAreNamed) optionalParameterCount++; 442 if (parameters.optionalParametersAreNamed) optionalParameterCount++;
445 443
446 expressions.add(code); 444 expressions.add(code);
447 445
448 // TODO(sra): Don't use LiteralString for non-strings.
449 List tearOffInfo = [new jsAst.LiteralString(callSelectorString)]; 446 List tearOffInfo = [new jsAst.LiteralString(callSelectorString)];
450 447
451 if (needsStubs || canTearOff) { 448 if (needsStubs || canTearOff) {
452 addParameterStubs(member, (Selector selector, jsAst.Fun function) { 449 addParameterStubs(member, (Selector selector, jsAst.Fun function) {
453 expressions.add(function); 450 expressions.add(function);
454 if (member.isInstanceMember()) { 451 if (member.isInstanceMember()) {
455 Set invokedSelectors = 452 Set invokedSelectors =
456 compiler.codegenWorld.invokedNames[member.name]; 453 compiler.codegenWorld.invokedNames[member.name];
457 expressions.add(js.string(namer.invocationName(selector))); 454 expressions.add(js.string(namer.invocationName(selector)));
458 } else { 455 } else {
459 expressions.add(js('null')); 456 expressions.add("null");
460 // TOOD(ahe): Since we know when reading static data versus instance 457 // TOOD(ahe): Since we know when reading static data versus instance
461 // data, we can eliminate this element. 458 // data, we can eliminate this element.
462 } 459 }
463 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[ 460 Set<Selector> callSelectors = compiler.codegenWorld.invokedNames[
464 namer.closureInvocationSelectorName]; 461 namer.closureInvocationSelectorName];
465 Selector callSelector = selector.toCallSelector(); 462 Selector callSelector = selector.toCallSelector();
466 String callSelectorString = 'null'; 463 String callSelectorString = 'null';
467 if (canTearOff && callSelectors != null && 464 if (canTearOff && callSelectors != null &&
468 callSelectors.contains(callSelector)) { 465 callSelectors.contains(callSelector)) {
469 callSelectorString = '"${namer.invocationName(callSelector)}"'; 466 callSelectorString = '"${namer.invocationName(callSelector)}"';
(...skipping 10 matching lines...) Expand all
480 memberType = body.constructor.type; 477 memberType = body.constructor.type;
481 } else { 478 } else {
482 memberType = member.type; 479 memberType = member.type;
483 } 480 }
484 if (memberType.containsTypeVariables) { 481 if (memberType.containsTypeVariables) {
485 jsAst.Expression thisAccess = js(r'this.$receiver'); 482 jsAst.Expression thisAccess = js(r'this.$receiver');
486 memberTypeExpression = 483 memberTypeExpression =
487 backend.rti.getSignatureEncoding(memberType, thisAccess); 484 backend.rti.getSignatureEncoding(memberType, thisAccess);
488 } else { 485 } else {
489 memberTypeExpression = 486 memberTypeExpression =
490 js.number(task.metadataEmitter.reifyType(memberType)); 487 js.toExpression(task.metadataEmitter.reifyType(memberType));
491 } 488 }
492 } else { 489 } else {
493 memberTypeExpression = js('null'); 490 memberTypeExpression = js('null');
494 } 491 }
495 492
496 expressions 493 expressions
497 ..addAll(tearOffInfo) 494 ..addAll(tearOffInfo)
498 ..add((tearOffName == null || member.isAccessor()) 495 ..add((tearOffName == null || member.isAccessor())
499 ? js("null") : js.string(tearOffName)) 496 ? js("null") : js.string(tearOffName))
500 ..add(js.number(requiredParameterCount)) 497 ..add(requiredParameterCount)
501 ..add(js.number(optionalParameterCount)) 498 ..add(optionalParameterCount)
502 ..add(memberTypeExpression) 499 ..add(memberTypeExpression)
503 ..addAll( 500 ..addAll(task.metadataEmitter.reifyDefaultArguments(member));
504 task.metadataEmitter.reifyDefaultArguments(member).map(js.number));
505 501
506 if (canBeReflected || canBeApplied) { 502 if (canBeReflected || canBeApplied) {
507 parameters.forEachParameter((Element parameter) { 503 parameters.forEachParameter((Element parameter) {
508 expressions.add( 504 expressions.add(task.metadataEmitter.reifyName(parameter.name));
509 js.number(task.metadataEmitter.reifyName(parameter.name)));
510 if (backend.mustRetainMetadata) { 505 if (backend.mustRetainMetadata) {
511 List<MetadataAnnotation> annotations = parameter.metadata.toList(); 506 List<MetadataAnnotation> annotations = parameter.metadata.toList();
512 Iterable<int> metadataIndices = 507 Iterable<int> metadataIndices =
513 annotations.map((MetadataAnnotation annotation) { 508 annotations.map((MetadataAnnotation annotation) {
514 Constant constant = 509 Constant constant =
515 backend.constants.getConstantForMetadata(annotation); 510 backend.constants.getConstantForMetadata(annotation);
516 backend.constants.addCompileTimeConstantForEmission(constant); 511 backend.constants.addCompileTimeConstantForEmission(constant);
517 return task.metadataEmitter.reifyMetadata(annotation); 512 return task.metadataEmitter.reifyMetadata(annotation);
518 }); 513 });
519 expressions.add( 514 expressions.add(metadataIndices.isNotEmpty ? metadataIndices.toList()
520 new jsAst.ArrayInitializer.from(metadataIndices.map(js.number))); 515 : js('[]'));
521 } 516 }
522 }); 517 });
523 } 518 }
524 if (canBeReflected) { 519 if (canBeReflected) {
525 jsAst.LiteralString reflectionName; 520 jsAst.LiteralString reflectionName;
526 if (member.isConstructor()) { 521 if (member.isConstructor()) {
527 String reflectionNameString = task.getReflectionName(member, name); 522 String reflectionNameString = task.getReflectionName(member, name);
528 reflectionName = 523 reflectionName =
529 new jsAst.LiteralString( 524 new jsAst.LiteralString(
530 '"new ${Elements.reconstructConstructorName(member)}"'); 525 '"new ${Elements.reconstructConstructorName(member)}"');
531 } else { 526 } else {
532 reflectionName = js.string(member.name); 527 reflectionName = js.string(member.name);
533 } 528 }
534 expressions 529 expressions
535 ..add(reflectionName) 530 ..add(reflectionName)
536 ..addAll(task.metadataEmitter.computeMetadata(member).map(js.number)); 531 ..addAll(task.metadataEmitter.computeMetadata(member));
537 } else if (isClosure && canBeApplied) { 532 } else if (isClosure && canBeApplied) {
538 expressions.add(js.string(member.name)); 533 expressions.add(js.string(member.name));
539 } 534 }
540 builder.addProperty(name, new jsAst.ArrayInitializer.from(expressions)); 535
536 builder.addProperty(name, js.toExpression(expressions));
541 } 537 }
542 538
543 void addMemberField(VariableElement member, ClassBuilder builder) { 539 void addMemberField(VariableElement member, ClassBuilder builder) {
544 // For now, do nothing. 540 // For now, do nothing.
545 } 541 }
546 } 542 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698