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

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

Issue 23045004: Throw when reflecting on elements not covered by a `MirrorsUsed` annotation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 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 /** 7 /**
8 * A function element that represents a closure call. The signature is copied 8 * A function element that represents a closure call. The signature is copied
9 * from the given element. 9 * from the given element.
10 */ 10 */
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 // characters. 280 // characters.
281 static const FIELD_CODE_CHARACTERS = r"<=>?@{|}~%&'()*"; 281 static const FIELD_CODE_CHARACTERS = r"<=>?@{|}~%&'()*";
282 static const NO_FIELD_CODE = 0; 282 static const NO_FIELD_CODE = 0;
283 static const FIRST_FIELD_CODE = 1; 283 static const FIRST_FIELD_CODE = 1;
284 static const RANGE1_FIRST = 0x3c; // <=>?@ encodes 1..5 284 static const RANGE1_FIRST = 0x3c; // <=>?@ encodes 1..5
285 static const RANGE1_LAST = 0x40; 285 static const RANGE1_LAST = 0x40;
286 static const RANGE2_FIRST = 0x7b; // {|}~ encodes 6..9 286 static const RANGE2_FIRST = 0x7b; // {|}~ encodes 6..9
287 static const RANGE2_LAST = 0x7e; 287 static const RANGE2_LAST = 0x7e;
288 static const RANGE3_FIRST = 0x25; // %&'()*+ encodes 10..16 288 static const RANGE3_FIRST = 0x25; // %&'()*+ encodes 10..16
289 static const RANGE3_LAST = 0x2b; 289 static const RANGE3_LAST = 0x2b;
290 static const REFLECTION_MARKER = 0x2d;
290 291
291 jsAst.FunctionDeclaration get generateAccessorFunction { 292 jsAst.FunctionDeclaration get generateAccessorFunction {
292 const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1; 293 const RANGE1_SIZE = RANGE1_LAST - RANGE1_FIRST + 1;
293 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; 294 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1;
294 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); 295 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST);
295 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); 296 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST);
296 const RANGE3_ADJUST = 297 const RANGE3_ADJUST =
297 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); 298 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST);
298 299
299 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; 300 String receiverParamName = compiler.enableMinification ? "r" : "receiver";
300 String valueParamName = compiler.enableMinification ? "v" : "value"; 301 String valueParamName = compiler.enableMinification ? "v" : "value";
301 302
302 // function generateAccessor(field, prototype) { 303 // function generateAccessor(field, prototype) {
303 jsAst.Fun fun = js.fun(['field', 'prototype'], [ 304 jsAst.Fun fun = js.fun(['field', 'prototype'], [
304 js('var len = field.length'), 305 js('var len = field.length'),
305 js('var code = field.charCodeAt(len - 1)'), 306 js('var code = field.charCodeAt(len - 1)'),
307 js('var reflectable = false'),
308 js.if_('code == $REFLECTION_MARKER', [
309 js('len--'),
310 js('code = field.charCodeAt(len - 1)'),
311 js('field = field.substring(0, len)'),
312 js('reflectable = true')
313 ]),
306 js('code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))' 314 js('code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))'
307 ' ? code - $RANGE1_ADJUST' 315 ' ? code - $RANGE1_ADJUST'
308 ' : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))' 316 ' : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))'
309 ' ? code - $RANGE2_ADJUST' 317 ' ? code - $RANGE2_ADJUST'
310 ' : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST))' 318 ' : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST))'
311 ' ? code - $RANGE3_ADJUST' 319 ' ? code - $RANGE3_ADJUST'
312 ' : $NO_FIELD_CODE'), 320 ' : $NO_FIELD_CODE'),
313 321
314 // if (needsAccessor) { 322 // if (needsAccessor) {
315 js.if_('code', [ 323 js.if_('code', [
316 js('var getterCode = code & 3'), 324 js('var getterCode = code & 3'),
317 js('var setterCode = code >> 2'), 325 js('var setterCode = code >> 2'),
318 js('var accessorName = field = field.substring(0, len - 1)'), 326 js('var accessorName = field = field.substring(0, len - 1)'),
319 327
320 js('var divider = field.indexOf(":")'), 328 js('var divider = field.indexOf(":")'),
321 js.if_('divider > 0', [ // Colon never in first position. 329 js.if_('divider > 0', [ // Colon never in first position.
322 js('accessorName = field.substring(0, divider)'), 330 js('accessorName = field.substring(0, divider)'),
323 js('field = field.substring(divider + 1)') 331 js('field = field.substring(divider + 1)')
324 ]), 332 ]),
325 333
326 // if (needsGetter) { 334 // if (needsGetter) {
327 js.if_('getterCode', [ 335 js.if_('getterCode', [
328 js('var args = (getterCode & 2) ? "$receiverParamName" : ""'), 336 js('var args = (getterCode & 2) ? "$receiverParamName" : ""'),
329 js('var receiver = (getterCode & 1) ? "this" : "$receiverParamName"'), 337 js('var receiver = (getterCode & 1) ? "this" : "$receiverParamName"'),
330 js('var body = "return " + receiver + "." + field'), 338 js('var body = "return " + receiver + "." + field'),
331 js('prototype["${namer.getterPrefix}" + accessorName] = ' 339 js('prototype["${namer.getterPrefix}" + accessorName] = '
332 'new Function(args, body)') 340 'new Function(args, body)'),
341 js('prototype["${namer.getterPrefix}" + accessorName].\$reflectable ='
ngeoffray 2013/08/29 07:45:49 Please move $reflectable to the namer.
karlklose 2013/08/29 15:33:37 Done.
342 ' reflectable')
ngeoffray 2013/08/29 07:45:49 Only add it if reflectable is true?
karlklose 2013/08/29 15:33:37 Done.
333 ]), 343 ]),
334 344
335 // if (needsSetter) { 345 // if (needsSetter) {
336 js.if_('setterCode', [ 346 js.if_('setterCode', [
337 js('var args = (setterCode & 2)' 347 js('var args = (setterCode & 2)'
338 ' ? "$receiverParamName,${_}$valueParamName"' 348 ' ? "$receiverParamName,${_}$valueParamName"'
339 ' : "$valueParamName"'), 349 ' : "$valueParamName"'),
340 js('var receiver = (setterCode & 1) ? "this" : "$receiverParamName"'), 350 js('var receiver = (setterCode & 1) ? "this" : "$receiverParamName"'),
341 js('var body = receiver + "." + field + "$_=$_$valueParamName"'), 351 js('var body = receiver + "." + field + "$_=$_$valueParamName"'),
342 js('prototype["${namer.setterPrefix}" + accessorName] = ' 352 js('prototype["${namer.setterPrefix}" + accessorName] = '
343 'new Function(args, body)') 353 'new Function(args, body)'),
354 js('prototype["${namer.setterPrefix}" + accessorName].\$reflectable ='
355 ' reflectable')
ngeoffray 2013/08/29 07:45:49 ditto.
karlklose 2013/08/29 15:33:37 Done.
344 ]), 356 ]),
345 357
346 ]), 358 ]),
347 359
348 // return field; 360 // return field;
349 js.return_('field') 361 js.return_('field')
350 ]); 362 ]);
351 363
352 return new jsAst.FunctionDeclaration( 364 return new jsAst.FunctionDeclaration(
353 new jsAst.VariableDeclaration('generateAccessor'), 365 new jsAst.VariableDeclaration('generateAccessor'),
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after
1092 } else { 1104 } else {
1093 body = [js.return_(js('this')[namer.getName(member)](argumentsBuffer))]; 1105 body = [js.return_(js('this')[namer.getName(member)](argumentsBuffer))];
1094 } 1106 }
1095 1107
1096 jsAst.Fun function = js.fun(parametersBuffer, body); 1108 jsAst.Fun function = js.fun(parametersBuffer, body);
1097 1109
1098 defineStub(invocationName, function); 1110 defineStub(invocationName, function);
1099 1111
1100 String reflectionName = getReflectionName(selector, invocationName); 1112 String reflectionName = getReflectionName(selector, invocationName);
1101 if (reflectionName != null) { 1113 if (reflectionName != null) {
1102 defineStub('+$reflectionName', js('0')); 1114 var reflectable =
1115 js(backend.isAccessibleByReflection(member) ? '1' : '0');
1116 defineStub('+$reflectionName', reflectable);
1103 } 1117 }
1104 } 1118 }
1105 1119
1106 void addParameterStubs(FunctionElement member, 1120 void addParameterStubs(FunctionElement member,
1107 DefineStubFunction defineStub) { 1121 DefineStubFunction defineStub) {
1108 // We fill the lists depending on the selector. For example, 1122 // We fill the lists depending on the selector. For example,
1109 // take method foo: 1123 // take method foo:
1110 // foo(a, b, {c, d}); 1124 // foo(a, b, {c, d});
1111 // 1125 //
1112 // We may have multiple ways of calling foo: 1126 // We may have multiple ways of calling foo:
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 jsAst.Expression code = backend.generatedCode[member]; 1277 jsAst.Expression code = backend.generatedCode[member];
1264 if (code == null) return; 1278 if (code == null) return;
1265 String name = namer.getName(member); 1279 String name = namer.getName(member);
1266 if (backend.isInterceptedMethod(member)) { 1280 if (backend.isInterceptedMethod(member)) {
1267 interceptorInvocationNames.add(name); 1281 interceptorInvocationNames.add(name);
1268 } 1282 }
1269 code = extendWithMetadata(member, code); 1283 code = extendWithMetadata(member, code);
1270 builder.addProperty(name, code); 1284 builder.addProperty(name, code);
1271 String reflectionName = getReflectionName(member, name); 1285 String reflectionName = getReflectionName(member, name);
1272 if (reflectionName != null) { 1286 if (reflectionName != null) {
1273 builder.addProperty('+$reflectionName', js('0')); 1287 var reflectable =
1288 js(backend.isAccessibleByReflection(member) ? '1' : '0');
1289 builder.addProperty('+$reflectionName', reflectable);
1274 } 1290 }
1275 code = backend.generatedBailoutCode[member]; 1291 code = backend.generatedBailoutCode[member];
1276 if (code != null) { 1292 if (code != null) {
1277 builder.addProperty(namer.getBailoutName(member), code); 1293 builder.addProperty(namer.getBailoutName(member), code);
1278 } 1294 }
1279 FunctionElement function = member; 1295 FunctionElement function = member;
1280 FunctionSignature parameters = function.computeSignature(compiler); 1296 FunctionSignature parameters = function.computeSignature(compiler);
1281 if (!parameters.optionalParameters.isEmpty) { 1297 if (!parameters.optionalParameters.isEmpty) {
1282 addParameterStubs(member, builder.addProperty); 1298 addParameterStubs(member, builder.addProperty);
1283 } 1299 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1318 1334
1319 String getReflectionNameInternal(elementOrSelector, String mangledName) { 1335 String getReflectionNameInternal(elementOrSelector, String mangledName) {
1320 String name = elementOrSelector.name.slowToString(); 1336 String name = elementOrSelector.name.slowToString();
1321 if (elementOrSelector.isGetter()) return name; 1337 if (elementOrSelector.isGetter()) return name;
1322 if (elementOrSelector.isSetter()) { 1338 if (elementOrSelector.isSetter()) {
1323 if (!mangledName.startsWith(namer.setterPrefix)) return '$name='; 1339 if (!mangledName.startsWith(namer.setterPrefix)) return '$name=';
1324 String base = mangledName.substring(namer.setterPrefix.length); 1340 String base = mangledName.substring(namer.setterPrefix.length);
1325 String getter = '${namer.getterPrefix}$base'; 1341 String getter = '${namer.getterPrefix}$base';
1326 mangledFieldNames[getter] = name; 1342 mangledFieldNames[getter] = name;
1327 recordedMangledNames.add(getter); 1343 recordedMangledNames.add(getter);
1328 return null; 1344 // TODO(karlklose,ahe): we do not actually need to store information
1345 // about the name of this setter in the output, but it is needed for
1346 // marking the function as invokable by reflection.
1347 return '$name=';
1329 } 1348 }
1330 if (elementOrSelector is Selector 1349 if (elementOrSelector is Selector
1331 || elementOrSelector.isFunction() 1350 || elementOrSelector.isFunction()
1332 || elementOrSelector.isConstructor()) { 1351 || elementOrSelector.isConstructor()) {
1333 int requiredParameterCount; 1352 int requiredParameterCount;
1334 int optionalParameterCount; 1353 int optionalParameterCount;
1335 String namedArguments = ''; 1354 String namedArguments = '';
1336 bool isConstructor = false; 1355 bool isConstructor = false;
1337 if (elementOrSelector is Selector) { 1356 if (elementOrSelector is Selector) {
1338 Selector selector = elementOrSelector; 1357 Selector selector = elementOrSelector;
(...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after
1854 } 1873 }
1855 } 1874 }
1856 int code = getterCode + (setterCode << 2); 1875 int code = getterCode + (setterCode << 2);
1857 if (code == 0) { 1876 if (code == 0) {
1858 compiler.reportInternalError( 1877 compiler.reportInternalError(
1859 field, 'Internal error: code is 0 ($element/$field)'); 1878 field, 'Internal error: code is 0 ($element/$field)');
1860 } else { 1879 } else {
1861 buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]); 1880 buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]);
1862 } 1881 }
1863 } 1882 }
1883 if (backend.isAccessibleByReflection(field)) {
1884 buffer.write(new String.fromCharCode(REFLECTION_MARKER));
1885 }
1864 } 1886 }
1865 }); 1887 });
1866 } 1888 }
1867 1889
1868 bool fieldsAdded = buffer.length > bufferClassLength; 1890 bool fieldsAdded = buffer.length > bufferClassLength;
1869 String compactClassData = buffer.toString(); 1891 String compactClassData = buffer.toString();
1870 jsAst.Expression classDataNode = js.string(compactClassData); 1892 jsAst.Expression classDataNode = js.string(compactClassData);
1871 if (hasMetadata) { 1893 if (hasMetadata) {
1872 fieldMetadata.insert(0, classDataNode); 1894 fieldMetadata.insert(0, classDataNode);
1873 classDataNode = new jsAst.ArrayInitializer.from(fieldMetadata); 1895 classDataNode = new jsAst.ArrayInitializer.from(fieldMetadata);
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
2293 .toSet(); 2315 .toSet();
2294 2316
2295 for (Element element in Elements.sortedByPosition(elements)) { 2317 for (Element element in Elements.sortedByPosition(elements)) {
2296 CodeBuffer buffer = bufferForElement(element, eagerBuffer); 2318 CodeBuffer buffer = bufferForElement(element, eagerBuffer);
2297 jsAst.Expression code = backend.generatedCode[element]; 2319 jsAst.Expression code = backend.generatedCode[element];
2298 String name = namer.getName(element); 2320 String name = namer.getName(element);
2299 code = extendWithMetadata(element, code); 2321 code = extendWithMetadata(element, code);
2300 emitStaticFunction(buffer, name, code); 2322 emitStaticFunction(buffer, name, code);
2301 String reflectionName = getReflectionName(element, name); 2323 String reflectionName = getReflectionName(element, name);
2302 if (reflectionName != null) { 2324 if (reflectionName != null) {
2303 buffer.write(',$n$n"+$reflectionName":${_}0'); 2325 var reflectable = backend.isAccessibleByReflection(element) ? 1 : 0;
2326 buffer.write(',$n$n"+$reflectionName":${_}$reflectable');
2304 } 2327 }
2305 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; 2328 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element];
2306 if (bailoutCode != null) { 2329 if (bailoutCode != null) {
2307 pendingElementsWithBailouts.remove(element); 2330 pendingElementsWithBailouts.remove(element);
2308 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); 2331 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode);
2309 } 2332 }
2310 } 2333 }
2311 2334
2312 if (!pendingElementsWithBailouts.isEmpty) { 2335 if (!pendingElementsWithBailouts.isEmpty) {
2313 addComment('pendingElementsWithBailouts', eagerBuffer); 2336 addComment('pendingElementsWithBailouts', eagerBuffer);
(...skipping 1757 matching lines...) Expand 10 before | Expand all | Expand 10 after
4071 var functions = []; 4094 var functions = [];
4072 function processStatics(descriptor) { 4095 function processStatics(descriptor) {
4073 for (var property in descriptor) { 4096 for (var property in descriptor) {
4074 if (!hasOwnProperty.call(descriptor, property)) continue; 4097 if (!hasOwnProperty.call(descriptor, property)) continue;
4075 if (property === "") continue; 4098 if (property === "") continue;
4076 var element = descriptor[property]; 4099 var element = descriptor[property];
4077 var firstChar = property.substring(0, 1); 4100 var firstChar = property.substring(0, 1);
4078 var previousProperty; 4101 var previousProperty;
4079 if (firstChar === "+") { 4102 if (firstChar === "+") {
4080 mangledGlobalNames[previousProperty] = property.substring(1); 4103 mangledGlobalNames[previousProperty] = property.substring(1);
4081 if (element && element.length) ''' // Breaking long line. 4104 descriptor[previousProperty].\$reflectable = ''' // Break long line.
4105 '''(descriptor[property] == 1);
4106 if (element && element.length) ''' // Break long line.
4082 '''init.interfaces[previousProperty] = element; 4107 '''init.interfaces[previousProperty] = element;
4083 } else if (firstChar === "@") { 4108 } else if (firstChar === "@") {
4084 property = property.substring(1); 4109 property = property.substring(1);
4085 ${namer.CURRENT_ISOLATE}[property][$metadataField] = element; 4110 ${namer.CURRENT_ISOLATE}[property][$metadataField] = element;
4086 } else if (typeof element === "function") { 4111 } else if (typeof element === "function") {
4087 ${namer.CURRENT_ISOLATE}[previousProperty = property] = element; 4112 ${namer.CURRENT_ISOLATE}[previousProperty = property] = element;
4088 functions.push(property); 4113 functions.push(property);
4089 } else { 4114 } else {
4090 previousProperty = property; 4115 previousProperty = property;
4091 var newDesc = {}; 4116 var newDesc = {};
4092 var previousProp; 4117 var previousProp;
4093 for (var prop in element) { 4118 for (var prop in element) {
4094 if (!hasOwnProperty.call(element, prop)) continue; 4119 if (!hasOwnProperty.call(element, prop)) continue;
4095 firstChar = prop.substring(0, 1); 4120 firstChar = prop.substring(0, 1);
4096 if (prop === "static") { 4121 if (prop === "static") {
4097 processStatics(init.statics[property] = element[prop]); 4122 processStatics(init.statics[property] = element[prop]);
4098 } else if (firstChar === "+") { 4123 } else if (firstChar === "+") {
4099 mangledNames[previousProp] = prop.substring(1); 4124 mangledNames[previousProp] = prop.substring(1);
4125 element[previousProp].\$reflectable = ''' // Break long line.
4126 '''(element[prop] == 1);
4100 } else if (firstChar === "@" && prop !== "@") { 4127 } else if (firstChar === "@" && prop !== "@") {
4101 newDesc[prop.substring(1)][$metadataField] = element[prop]; 4128 newDesc[prop.substring(1)][$metadataField] = element[prop];
4102 } else { 4129 } else {
4103 newDesc[previousProp = prop] = element[prop]; 4130 newDesc[previousProp = prop] = element[prop];
4104 } 4131 }
4105 } 4132 }
4106 $classesCollector[property] = newDesc; 4133 $classesCollector[property] = newDesc;
4107 classes.push(property); 4134 classes.push(property);
4108 } 4135 }
4109 } 4136 }
(...skipping 11 matching lines...) Expand all
4121 4148
4122 const String HOOKS_API_USAGE = """ 4149 const String HOOKS_API_USAGE = """
4123 // The code supports the following hooks: 4150 // The code supports the following hooks:
4124 // dartPrint(message) - if this function is defined it is called 4151 // dartPrint(message) - if this function is defined it is called
4125 // instead of the Dart [print] method. 4152 // instead of the Dart [print] method.
4126 // dartMainRunner(main) - if this function is defined, the Dart [main] 4153 // dartMainRunner(main) - if this function is defined, the Dart [main]
4127 // method will not be invoked directly. 4154 // method will not be invoked directly.
4128 // Instead, a closure that will invoke [main] is 4155 // Instead, a closure that will invoke [main] is
4129 // passed to [dartMainRunner]. 4156 // passed to [dartMainRunner].
4130 """; 4157 """;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698