| OLD | NEW |
| 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 /// Enables debugging of fast/slow objects using V8-specific primitives. | 7 /// Enables debugging of fast/slow objects using V8-specific primitives. |
| 8 const DEBUG_FAST_OBJECTS = false; | 8 const DEBUG_FAST_OBJECTS = false; |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 1247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 if (backend.isInterceptedMethod(member)) { | 1258 if (backend.isInterceptedMethod(member)) { |
| 1259 interceptorInvocationNames.add(name); | 1259 interceptorInvocationNames.add(name); |
| 1260 } | 1260 } |
| 1261 code = extendWithMetadata(member, code); | 1261 code = extendWithMetadata(member, code); |
| 1262 builder.addProperty(name, code); | 1262 builder.addProperty(name, code); |
| 1263 String reflectionName = getReflectionName(member, name); | 1263 String reflectionName = getReflectionName(member, name); |
| 1264 if (reflectionName != null) { | 1264 if (reflectionName != null) { |
| 1265 var reflectable = | 1265 var reflectable = |
| 1266 js(backend.isAccessibleByReflection(member) ? '1' : '0'); | 1266 js(backend.isAccessibleByReflection(member) ? '1' : '0'); |
| 1267 builder.addProperty('+$reflectionName', reflectable); | 1267 builder.addProperty('+$reflectionName', reflectable); |
| 1268 jsAst.Node defaultValues = reifyDefaultArguments(member); |
| 1269 if (defaultValues != null) { |
| 1270 String unmangledName = member.name.slowToString(); |
| 1271 builder.addProperty('*$unmangledName', defaultValues); |
| 1272 } |
| 1268 } | 1273 } |
| 1269 code = backend.generatedBailoutCode[member]; | 1274 code = backend.generatedBailoutCode[member]; |
| 1270 if (code != null) { | 1275 if (code != null) { |
| 1271 builder.addProperty(namer.getBailoutName(member), code); | 1276 builder.addProperty(namer.getBailoutName(member), code); |
| 1272 } | 1277 } |
| 1273 FunctionElement function = member; | 1278 FunctionElement function = member; |
| 1274 FunctionSignature parameters = function.computeSignature(compiler); | 1279 FunctionSignature parameters = function.computeSignature(compiler); |
| 1275 if (!parameters.optionalParameters.isEmpty) { | 1280 if (!parameters.optionalParameters.isEmpty) { |
| 1276 addParameterStubs(member, builder.addProperty); | 1281 addParameterStubs(function, builder.addProperty); |
| 1277 } | 1282 } |
| 1278 } else if (!member.isField()) { | 1283 } else if (!member.isField()) { |
| 1279 compiler.internalError('unexpected kind: "${member.kind}"', | 1284 compiler.internalError('unexpected kind: "${member.kind}"', |
| 1280 element: member); | 1285 element: member); |
| 1281 } | 1286 } |
| 1282 emitExtraAccessors(member, builder); | 1287 emitExtraAccessors(member, builder); |
| 1283 } | 1288 } |
| 1284 | 1289 |
| 1285 /// Returns the "reflection name" of an [Element] or [Selector]. | 1290 /// Returns the "reflection name" of an [Element] or [Selector]. |
| 1286 /// The reflection name of a getter 'foo' is 'foo'. | 1291 /// The reflection name of a getter 'foo' is 'foo'. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1369 } else if (element.isClass()) { | 1374 } else if (element.isClass()) { |
| 1370 ClassElement cls = element; | 1375 ClassElement cls = element; |
| 1371 if (cls.isUnnamedMixinApplication) return null; | 1376 if (cls.isUnnamedMixinApplication) return null; |
| 1372 return cls.name.slowToString(); | 1377 return cls.name.slowToString(); |
| 1373 } | 1378 } |
| 1374 throw compiler.internalErrorOnElement( | 1379 throw compiler.internalErrorOnElement( |
| 1375 element, 'Do not know how to reflect on this $element'); | 1380 element, 'Do not know how to reflect on this $element'); |
| 1376 } | 1381 } |
| 1377 | 1382 |
| 1378 String namedParametersAsReflectionNames(Selector selector) { | 1383 String namedParametersAsReflectionNames(Selector selector) { |
| 1379 if (selector.orderedNamedArguments.isEmpty) return ''; | 1384 if (selector.getOrderedNamedArguments().isEmpty) return ''; |
| 1380 String names = | 1385 String names = selector.getOrderedNamedArguments().map( |
| 1381 selector.orderedNamedArguments.map((x) => x.slowToString()).join(':'); | 1386 (x) => x.slowToString()).join(':'); |
| 1382 return ':$names'; | 1387 return ':$names'; |
| 1383 } | 1388 } |
| 1384 | 1389 |
| 1385 /** | 1390 /** |
| 1386 * Documentation wanted -- johnniwinther | 1391 * Documentation wanted -- johnniwinther |
| 1387 * | 1392 * |
| 1388 * Invariant: [classElement] must be a declaration element. | 1393 * Invariant: [classElement] must be a declaration element. |
| 1389 */ | 1394 */ |
| 1390 void emitInstanceMembers(ClassElement classElement, | 1395 void emitInstanceMembers(ClassElement classElement, |
| 1391 ClassBuilder builder) { | 1396 ClassBuilder builder) { |
| (...skipping 984 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2376 for (Element element in Elements.sortedByPosition(elements)) { | 2381 for (Element element in Elements.sortedByPosition(elements)) { |
| 2377 CodeBuffer buffer = bufferForElement(element, eagerBuffer); | 2382 CodeBuffer buffer = bufferForElement(element, eagerBuffer); |
| 2378 jsAst.Expression code = backend.generatedCode[element]; | 2383 jsAst.Expression code = backend.generatedCode[element]; |
| 2379 String name = namer.getNameOfGlobalFunction(element); | 2384 String name = namer.getNameOfGlobalFunction(element); |
| 2380 code = extendWithMetadata(element, code); | 2385 code = extendWithMetadata(element, code); |
| 2381 emitStaticFunction(buffer, name, code); | 2386 emitStaticFunction(buffer, name, code); |
| 2382 String reflectionName = getReflectionName(element, name); | 2387 String reflectionName = getReflectionName(element, name); |
| 2383 if (reflectionName != null) { | 2388 if (reflectionName != null) { |
| 2384 var reflectable = backend.isAccessibleByReflection(element) ? 1 : 0; | 2389 var reflectable = backend.isAccessibleByReflection(element) ? 1 : 0; |
| 2385 buffer.write(',$n$n"+$reflectionName":${_}$reflectable'); | 2390 buffer.write(',$n$n"+$reflectionName":${_}$reflectable'); |
| 2391 jsAst.Node defaultValues = reifyDefaultArguments(element); |
| 2392 if (defaultValues != null) { |
| 2393 String unmangledName = element.name.slowToString(); |
| 2394 buffer.write(',$n$n"*$unmangledName":${_}'); |
| 2395 buffer.write(jsAst.prettyPrint(defaultValues, compiler)); |
| 2396 } |
| 2386 } | 2397 } |
| 2387 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; | 2398 jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; |
| 2388 if (bailoutCode != null) { | 2399 if (bailoutCode != null) { |
| 2389 pendingElementsWithBailouts.remove(element); | 2400 pendingElementsWithBailouts.remove(element); |
| 2390 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); | 2401 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); |
| 2391 } | 2402 } |
| 2392 } | 2403 } |
| 2393 | 2404 |
| 2394 if (!pendingElementsWithBailouts.isEmpty) { | 2405 if (!pendingElementsWithBailouts.isEmpty) { |
| 2395 addComment('pendingElementsWithBailouts', eagerBuffer); | 2406 addComment('pendingElementsWithBailouts', eagerBuffer); |
| (...skipping 1292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3688 metadata.add(constantReference(value)); | 3699 metadata.add(constantReference(value)); |
| 3689 } | 3700 } |
| 3690 } | 3701 } |
| 3691 } | 3702 } |
| 3692 if (metadata.isEmpty) return null; | 3703 if (metadata.isEmpty) return null; |
| 3693 return js.fun( | 3704 return js.fun( |
| 3694 [], [js.return_(new jsAst.ArrayInitializer.from(metadata))]); | 3705 [], [js.return_(new jsAst.ArrayInitializer.from(metadata))]); |
| 3695 }); | 3706 }); |
| 3696 } | 3707 } |
| 3697 | 3708 |
| 3709 jsAst.Node reifyDefaultArguments(FunctionElement function) { |
| 3710 FunctionSignature signature = function.computeSignature(compiler); |
| 3711 if (signature.optionalParameterCount == 0) return null; |
| 3712 List<int> defaultValues = <int>[]; |
| 3713 for (Element element in signature.orderedOptionalParameters) { |
| 3714 Constant value = |
| 3715 compiler.constantHandler.initialVariableValues[element]; |
| 3716 String stringRepresentation = (value == null) ? "null" |
| 3717 : jsAst.prettyPrint(constantReference(value), compiler).getText(); |
| 3718 defaultValues.add(addGlobalMetadata(stringRepresentation)); |
| 3719 } |
| 3720 return js.toExpression(defaultValues); |
| 3721 } |
| 3722 |
| 3698 int reifyMetadata(MetadataAnnotation annotation) { | 3723 int reifyMetadata(MetadataAnnotation annotation) { |
| 3699 Constant value = annotation.value; | 3724 Constant value = annotation.value; |
| 3700 if (value == null) { | 3725 if (value == null) { |
| 3701 compiler.reportInternalError( | 3726 compiler.reportInternalError( |
| 3702 annotation, 'Internal error: value is null'); | 3727 annotation, 'Internal error: value is null'); |
| 3703 return -1; | 3728 return -1; |
| 3704 } | 3729 } |
| 3705 return addGlobalMetadata( | 3730 return addGlobalMetadata( |
| 3706 jsAst.prettyPrint(constantReference(value), compiler).getText()); | 3731 jsAst.prettyPrint(constantReference(value), compiler).getText()); |
| 3707 } | 3732 } |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4260 void warnNotImplemented(Element element, String message) { | 4285 void warnNotImplemented(Element element, String message) { |
| 4261 compiler.reportMessage(compiler.spanFromSpannable(element), | 4286 compiler.reportMessage(compiler.spanFromSpannable(element), |
| 4262 MessageKind.GENERIC.error({'text': message}), | 4287 MessageKind.GENERIC.error({'text': message}), |
| 4263 api.Diagnostic.WARNING); | 4288 api.Diagnostic.WARNING); |
| 4264 } | 4289 } |
| 4265 | 4290 |
| 4266 // TODO(ahe): This code should be integrated in finishClasses. | 4291 // TODO(ahe): This code should be integrated in finishClasses. |
| 4267 String getReflectionDataParser() { | 4292 String getReflectionDataParser() { |
| 4268 String metadataField = '"${namer.metadataField}"'; | 4293 String metadataField = '"${namer.metadataField}"'; |
| 4269 String reflectableField = namer.reflectableField; | 4294 String reflectableField = namer.reflectableField; |
| 4295 String defaultValuesField = namer.defaultValuesField; |
| 4296 String methodsWithOptionalArgumentsField = |
| 4297 namer.methodsWithOptionalArgumentsField; |
| 4270 return ''' | 4298 return ''' |
| 4271 (function (reflectionData) { | 4299 (function (reflectionData) { |
| 4272 ''' | 4300 ''' |
| 4273 // [map] returns an object literal that V8 shouldn't try to optimize with a | 4301 // [map] returns an object literal that V8 shouldn't try to optimize with a |
| 4274 // hidden class. This prevents a potential performance problem where V8 tries | 4302 // hidden class. This prevents a potential performance problem where V8 tries |
| 4275 // to build a hidden class for an object used as a hashMap. | 4303 // to build a hidden class for an object used as a hashMap. |
| 4276 ''' | 4304 ''' |
| 4277 function map(x){x={x:x};delete x.x;return x} | 4305 function map(x){x={x:x};delete x.x;return x} |
| 4278 if (!init.libraries) init.libraries = []; | 4306 if (!init.libraries) init.libraries = []; |
| 4279 if (!init.mangledNames) init.mangledNames = map(); | 4307 if (!init.mangledNames) init.mangledNames = map(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4318 var previousProperty; | 4346 var previousProperty; |
| 4319 if (firstChar === "+") { | 4347 if (firstChar === "+") { |
| 4320 mangledGlobalNames[previousProperty] = property.substring(1); | 4348 mangledGlobalNames[previousProperty] = property.substring(1); |
| 4321 if (descriptor[property] == 1) ''' // Break long line. | 4349 if (descriptor[property] == 1) ''' // Break long line. |
| 4322 '''descriptor[previousProperty].$reflectableField = 1; | 4350 '''descriptor[previousProperty].$reflectableField = 1; |
| 4323 if (element && element.length) ''' // Break long line. | 4351 if (element && element.length) ''' // Break long line. |
| 4324 '''init.interfaces[previousProperty] = element; | 4352 '''init.interfaces[previousProperty] = element; |
| 4325 } else if (firstChar === "@") { | 4353 } else if (firstChar === "@") { |
| 4326 property = property.substring(1); | 4354 property = property.substring(1); |
| 4327 ${namer.CURRENT_ISOLATE}[property][$metadataField] = element; | 4355 ${namer.CURRENT_ISOLATE}[property][$metadataField] = element; |
| 4356 } else if (firstChar === "*") { |
| 4357 globalObject[previousProperty].$defaultValuesField = element; |
| 4358 var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; |
| 4359 if (!optionalMethods) { |
| 4360 descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} |
| 4361 } |
| 4362 optionalMethods[property] = previousProperty; |
| 4328 } else if (typeof element === "function") { | 4363 } else if (typeof element === "function") { |
| 4329 globalObject[previousProperty = property] = element; | 4364 globalObject[previousProperty = property] = element; |
| 4330 functions.push(property); | 4365 functions.push(property); |
| 4331 init.globalFunctions[property] = element; | 4366 init.globalFunctions[property] = element; |
| 4332 } else { | 4367 } else { |
| 4333 previousProperty = property; | 4368 previousProperty = property; |
| 4334 var newDesc = {}; | 4369 var newDesc = {}; |
| 4335 var previousProp; | 4370 var previousProp; |
| 4336 for (var prop in element) { | 4371 for (var prop in element) { |
| 4337 if (!hasOwnProperty.call(element, prop)) continue; | 4372 if (!hasOwnProperty.call(element, prop)) continue; |
| 4338 firstChar = prop.substring(0, 1); | 4373 firstChar = prop.substring(0, 1); |
| 4339 if (prop === "static") { | 4374 if (prop === "static") { |
| 4340 processStatics(init.statics[property] = element[prop]); | 4375 processStatics(init.statics[property] = element[prop]); |
| 4341 } else if (firstChar === "+") { | 4376 } else if (firstChar === "+") { |
| 4342 mangledNames[previousProp] = prop.substring(1); | 4377 mangledNames[previousProp] = prop.substring(1); |
| 4343 if (element[prop] == 1) ''' // Break long line. | 4378 if (element[prop] == 1) ''' // Break long line. |
| 4344 '''element[previousProp].$reflectableField = 1; | 4379 '''element[previousProp].$reflectableField = 1; |
| 4345 } else if (firstChar === "@" && prop !== "@") { | 4380 } else if (firstChar === "@" && prop !== "@") { |
| 4346 newDesc[prop.substring(1)][$metadataField] = element[prop]; | 4381 newDesc[prop.substring(1)][$metadataField] = element[prop]; |
| 4382 } else if (firstChar === "*") { |
| 4383 newDesc[previousProp].$defaultValuesField = element[prop]; |
| 4384 var optionalMethods = newDesc.$methodsWithOptionalArgumentsField; |
| 4385 if (!optionalMethods) { |
| 4386 newDesc.$methodsWithOptionalArgumentsField = optionalMethods={} |
| 4387 } |
| 4388 optionalMethods[prop] = previousProp; |
| 4347 } else { | 4389 } else { |
| 4348 newDesc[previousProp = prop] = element[prop]; | 4390 newDesc[previousProp = prop] = element[prop]; |
| 4349 } | 4391 } |
| 4350 } | 4392 } |
| 4351 $classesCollector[property] = [globalObject, newDesc]; | 4393 $classesCollector[property] = [globalObject, newDesc]; |
| 4352 classes.push(property); | 4394 classes.push(property); |
| 4353 } | 4395 } |
| 4354 } | 4396 } |
| 4355 } | 4397 } |
| 4356 processStatics(descriptor); | 4398 processStatics(descriptor); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4367 | 4409 |
| 4368 const String HOOKS_API_USAGE = """ | 4410 const String HOOKS_API_USAGE = """ |
| 4369 // The code supports the following hooks: | 4411 // The code supports the following hooks: |
| 4370 // dartPrint(message) - if this function is defined it is called | 4412 // dartPrint(message) - if this function is defined it is called |
| 4371 // instead of the Dart [print] method. | 4413 // instead of the Dart [print] method. |
| 4372 // dartMainRunner(main) - if this function is defined, the Dart [main] | 4414 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 4373 // method will not be invoked directly. | 4415 // method will not be invoked directly. |
| 4374 // Instead, a closure that will invoke [main] is | 4416 // Instead, a closure that will invoke [main] is |
| 4375 // passed to [dartMainRunner]. | 4417 // passed to [dartMainRunner]. |
| 4376 """; | 4418 """; |
| OLD | NEW |