| OLD | NEW |
| 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 // TODO(ahe): Share these with js_helper.dart. | 7 // TODO(ahe): Share these with js_helper.dart. |
| 8 const FUNCTION_INDEX = 0; | 8 const FUNCTION_INDEX = 0; |
| 9 const NAME_INDEX = 1; | 9 const NAME_INDEX = 1; |
| 10 const CALL_NAME_INDEX = 2; | 10 const CALL_NAME_INDEX = 2; |
| 11 const REQUIRED_PARAMETER_INDEX = 3; | 11 const REQUIRED_PARAMETER_INDEX = 3; |
| 12 const OPTIONAL_PARAMETER_INDEX = 4; | 12 const OPTIONAL_PARAMETER_INDEX = 4; |
| 13 const DEFAULT_ARGUMENTS_INDEX = 5; | 13 const DEFAULT_ARGUMENTS_INDEX = 5; |
| 14 | 14 |
| 15 const bool VALIDATE_DATA = false; | 15 const bool VALIDATE_DATA = false; |
| 16 | 16 |
| 17 // TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses. | 17 // TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses. |
| 18 jsAst.Expression getReflectionDataParser(String classesCollector, | 18 jsAst.Expression getReflectionDataParser(String classesCollector, |
| 19 JavaScriptBackend backend) { | 19 JavaScriptBackend backend) { |
| 20 Namer namer = backend.namer; | 20 Namer namer = backend.namer; |
| 21 Compiler compiler = backend.compiler; | 21 Compiler compiler = backend.compiler; |
| 22 CodeEmitterTask emitter = backend.emitter; | 22 CodeEmitterTask emitter = backend.emitter; |
| 23 | 23 |
| 24 String metadataField = '"${namer.metadataField}"'; | 24 String metadataField = '"${namer.metadataField}"'; |
| 25 String reflectableField = namer.reflectableField; | 25 String reflectableField = namer.reflectableField; |
| 26 | 26 String reflectionInfoField = namer.reflectionInfoField; |
| 27 // TODO(ahe): Move this string constants to namer. | 27 String reflectionNameField = namer.reflectionNameField; |
| 28 String reflectionInfoField = r'$reflectionInfo'; | 28 String metadataIndexField = namer.metadataIndexField; |
| 29 String reflectionNameField = r'$reflectionName'; | |
| 30 String metadataIndexField = r'$metadataIndex'; | |
| 31 | |
| 32 String defaultValuesField = namer.defaultValuesField; | 29 String defaultValuesField = namer.defaultValuesField; |
| 33 String methodsWithOptionalArgumentsField = | 30 String methodsWithOptionalArgumentsField = |
| 34 namer.methodsWithOptionalArgumentsField; | 31 namer.methodsWithOptionalArgumentsField; |
| 35 | 32 |
| 36 String unmangledNameIndex = backend.mustRetainMetadata | 33 String unmangledNameIndex = backend.mustRetainMetadata |
| 37 ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3' | 34 ? ' 3 * optionalParameterCount + 2 * requiredParameterCount + 3' |
| 38 : ' 2 * optionalParameterCount + requiredParameterCount + 3'; | 35 : ' 2 * optionalParameterCount + requiredParameterCount + 3'; |
| 39 | 36 |
| 40 jsAst.Expression typeInformationAccess = | 37 jsAst.Expression typeInformationAccess = |
| 41 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPE_INFORMATION); | 38 emitter.generateEmbeddedGlobalAccess(embeddedNames.TYPE_INFORMATION); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 requiredParameterCount + optionalParameterCount != funcs[0].length; | 178 requiredParameterCount + optionalParameterCount != funcs[0].length; |
| 182 var functionTypeIndex = ${readFunctionType("array", "2")}; | 179 var functionTypeIndex = ${readFunctionType("array", "2")}; |
| 183 var unmangledNameIndex = $unmangledNameIndex; | 180 var unmangledNameIndex = $unmangledNameIndex; |
| 184 var isReflectable = array.length > unmangledNameIndex; | 181 var isReflectable = array.length > unmangledNameIndex; |
| 185 | 182 |
| 186 if (getterStubName) { | 183 if (getterStubName) { |
| 187 f = tearOff(funcs, array, isStatic, name, isIntercepted); | 184 f = tearOff(funcs, array, isStatic, name, isIntercepted); |
| 188 descriptor[name].\$getter = f; | 185 descriptor[name].\$getter = f; |
| 189 f.\$getterStub = true; | 186 f.\$getterStub = true; |
| 190 // Used to create an isolate using spawnFunction. | 187 // Used to create an isolate using spawnFunction. |
| 191 if (isStatic) #[name] = f; // embedded globalFunctions. | 188 if (isStatic) #globalFunctions[name] = f; |
| 192 originalDescriptor[getterStubName] = descriptor[getterStubName] = f; | 189 originalDescriptor[getterStubName] = descriptor[getterStubName] = f; |
| 193 funcs.push(f); | 190 funcs.push(f); |
| 194 if (getterStubName) functions.push(getterStubName); | 191 if (getterStubName) functions.push(getterStubName); |
| 195 f.\$stubName = getterStubName; | 192 f.\$stubName = getterStubName; |
| 196 f.\$callName = null; | 193 f.\$callName = null; |
| 197 if (isIntercepted) #[getterStubName] = true; // embedded interceptedNames. | 194 if (isIntercepted) #interceptedNames[getterStubName] = true; |
| 198 } | 195 } |
| 199 if (isReflectable) { | 196 if (isReflectable) { |
| 200 for (var i = 0; i < funcs.length; i++) { | 197 for (var i = 0; i < funcs.length; i++) { |
| 201 funcs[i].$reflectableField = 1; | 198 funcs[i].$reflectableField = 1; |
| 202 funcs[i].$reflectionInfoField = array; | 199 funcs[i].$reflectionInfoField = array; |
| 203 } | 200 } |
| 204 var mangledNames = isStatic ? # : #; // embedded mangledGlobalNames, mang
ledNames | 201 var mangledNames = isStatic ? #mangledGlobalNames : #mangledNames; |
| 205 var unmangledName = ${readString("array", "unmangledNameIndex")}; | 202 var unmangledName = ${readString("array", "unmangledNameIndex")}; |
| 206 // The function is either a getter, a setter, or a method. | 203 // The function is either a getter, a setter, or a method. |
| 207 // If it is a method, it might also have a tear-off closure. | 204 // If it is a method, it might also have a tear-off closure. |
| 208 // The unmangledName is the same as the getter-name. | 205 // The unmangledName is the same as the getter-name. |
| 209 var reflectionName = unmangledName; | 206 var reflectionName = unmangledName; |
| 210 if (getterStubName) mangledNames[getterStubName] = reflectionName; | 207 if (getterStubName) mangledNames[getterStubName] = reflectionName; |
| 211 if (isSetter) { | 208 if (isSetter) { |
| 212 reflectionName += "="; | 209 reflectionName += "="; |
| 213 } else if (!isGetter) { | 210 } else if (!isGetter) { |
| 214 reflectionName += ":" + requiredParameterCount + | 211 reflectionName += ":" + requiredParameterCount + |
| 215 ":" + optionalParameterCount; | 212 ":" + optionalParameterCount; |
| 216 } | 213 } |
| 217 mangledNames[name] = reflectionName; | 214 mangledNames[name] = reflectionName; |
| 218 funcs[0].$reflectionNameField = reflectionName; | 215 funcs[0].$reflectionNameField = reflectionName; |
| 219 funcs[0].$metadataIndexField = unmangledNameIndex + 1; | 216 funcs[0].$metadataIndexField = unmangledNameIndex + 1; |
| 220 if (optionalParameterCount) descriptor[unmangledName + "*"] = funcs[0]; | 217 if (optionalParameterCount) descriptor[unmangledName + "*"] = funcs[0]; |
| 221 } | 218 } |
| 222 } | 219 } |
| 223 ''', [globalFunctionsAccess, interceptedNamesAccess, | 220 ''', {'globalFunctions' : globalFunctionsAccess, |
| 224 mangledGlobalNamesAccess, mangledNamesAccess]); | 221 'interceptedNames': interceptedNamesAccess, |
| 222 'mangledGlobalNames': mangledGlobalNamesAccess, |
| 223 'mangledNames': mangledNamesAccess}); |
| 225 | 224 |
| 226 List<jsAst.Statement> tearOffCode = buildTearOffCode(backend); | 225 List<jsAst.Statement> tearOffCode = buildTearOffCode(backend); |
| 227 | 226 |
| 228 jsAst.Statement init = js.statement('''{ | 227 jsAst.Statement init = js.statement('''{ |
| 229 var functionCounter = 0; | 228 var functionCounter = 0; |
| 230 if (!#) # = []; // embedded libraries. | 229 if (!#) # = []; // embedded libraries. |
| 231 if (!#) # = map(); // embedded mangledNames. | 230 if (!#) # = map(); // embedded mangledNames. |
| 232 if (!#) # = map(); // embedded mangledGlobalNames. | 231 if (!#) # = map(); // embedded mangledGlobalNames. |
| 233 if (!#) # = map(); // embedded statics. | 232 if (!#) # = map(); // embedded statics. |
| 234 if (!#) # = map(); // embedded typeInformation. | 233 if (!#) # = map(); // embedded typeInformation. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 return new cache(this, funcs[0], null, name); | 370 return new cache(this, funcs[0], null, name); |
| 372 }; | 371 }; |
| 373 }''', [tearOffAccessExpression, tearOffAccessExpression]); | 372 }''', [tearOffAccessExpression, tearOffAccessExpression]); |
| 374 } | 373 } |
| 375 | 374 |
| 376 jsAst.Statement tearOff = js.statement(''' | 375 jsAst.Statement tearOff = js.statement(''' |
| 377 function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) { | 376 function tearOff(funcs, reflectionInfo, isStatic, name, isIntercepted) { |
| 378 var cache; | 377 var cache; |
| 379 return isStatic | 378 return isStatic |
| 380 ? function() { | 379 ? function() { |
| 381 if (cache === void 0) cache = #( | 380 if (cache === void 0) cache = #tearOff( |
| 382 this, funcs, reflectionInfo, true, [], name).prototype; | 381 this, funcs, reflectionInfo, true, [], name).prototype; |
| 383 return cache; | 382 return cache; |
| 384 } | 383 } |
| 385 : tearOffGetter(funcs, reflectionInfo, name, isIntercepted); | 384 : tearOffGetter(funcs, reflectionInfo, name, isIntercepted); |
| 386 }''', tearOffAccessExpression); | 385 }''', {'tearOff': tearOffAccessExpression}); |
| 387 | 386 |
| 388 return <jsAst.Statement>[tearOffGetter, tearOff]; | 387 return <jsAst.Statement>[tearOffGetter, tearOff]; |
| 389 } | 388 } |
| 390 | 389 |
| 391 String readString(String array, String index) { | 390 String readString(String array, String index) { |
| 392 return readChecked( | 391 return readChecked( |
| 393 array, index, 'result != null && typeof result != "string"', 'string'); | 392 array, index, 'result != null && typeof result != "string"', 'string'); |
| 394 } | 393 } |
| 395 | 394 |
| 396 String readInt(String array, String index) { | 395 String readInt(String array, String index) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 415 (function() { | 414 (function() { |
| 416 var result = $array[$index]; | 415 var result = $array[$index]; |
| 417 if ($check) { | 416 if ($check) { |
| 418 throw new Error( | 417 throw new Error( |
| 419 name + ": expected value of type \'$type\' at index " + ($index) + | 418 name + ": expected value of type \'$type\' at index " + ($index) + |
| 420 " but got " + (typeof result)); | 419 " but got " + (typeof result)); |
| 421 } | 420 } |
| 422 return result; | 421 return result; |
| 423 })()'''; | 422 })()'''; |
| 424 } | 423 } |
| OLD | NEW |