Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.startup_emitter.model_emitter; | 5 part of dart2js.js_emitter.startup_emitter.model_emitter; |
| 6 | 6 |
| 7 /// The name of the property that stores the tear-off getter on a static | 7 /// The name of the property that stores the tear-off getter on a static |
| 8 /// function. | 8 /// function. |
| 9 /// | 9 /// |
| 10 /// This property is only used when isolates are used. | 10 /// This property is only used when isolates are used. |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 | 61 |
| 62 (function() { | 62 (function() { |
| 63 // Copies the own properties from [from] to [to]. | 63 // Copies the own properties from [from] to [to]. |
| 64 function copyProperties(from, to) { | 64 function copyProperties(from, to) { |
| 65 var keys = Object.keys(from); | 65 var keys = Object.keys(from); |
| 66 for (var i = 0; i < keys.length; i++) { | 66 for (var i = 0; i < keys.length; i++) { |
| 67 to[keys[i]] = from[keys[i]]; | 67 to[keys[i]] = from[keys[i]]; |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 | 70 |
| 71 var supportsDirectProtoAccess = (function () { | |
| 72 var cls = function () {}; | |
| 73 cls.prototype = {'p': {}}; | |
| 74 var object = new cls(); | |
| 75 return object.__proto__ && | |
| 76 object.__proto__.p === cls.prototype.p; | |
| 77 })(); | |
| 78 | |
| 79 var functionsHaveName = (function() { | |
| 80 function t() {}; | |
| 81 return (typeof t.name == 'string') | |
| 82 })(); | |
| 83 | |
| 84 var isChrome = (typeof window != 'undefined') && | |
| 85 (typeof window.chrome != 'undefined'); | |
| 86 | |
| 87 // Sets the name property of functions, if the JS engine doesn't set the name | |
| 88 // itself. | |
| 89 // As of 2015 only IE doesn't set the name. | |
| 90 function setFunctionNamesIfNecessary(holders) { | |
| 91 if (functionsHaveName) return; | |
| 92 for (var i = 0; i < holders.length; i++) { | |
| 93 var holder = holders[i]; | |
| 94 var keys = Object.keys(holder); | |
| 95 for (var j = 0; j < keys.length; j++) { | |
| 96 var key = keys[j]; | |
| 97 var f = holder[key]; | |
| 98 if (typeof f == 'function') f.name = key; | |
| 99 } | |
| 100 } | |
| 101 } | |
| 102 | |
| 71 // Makes [cls] inherit from [sup]. | 103 // Makes [cls] inherit from [sup]. |
| 72 // On Chrome, Firefox and recent IEs this happens by updating the internal | 104 // On Chrome, Firefox and recent IEs this happens by updating the internal |
| 73 // proto-property of the classes 'prototype' field. | 105 // proto-property of the classes 'prototype' field. |
| 74 // Older IEs use `Object.create` and copy over the properties. | 106 // Older IEs use `Object.create` and copy over the properties. |
| 75 function inherit(cls, sup) { | 107 function inherit(cls, sup) { |
| 76 // TODO(floitsch): IE doesn't support changing the __proto__ property. There, | |
| 77 // we need to copy the properties instead. | |
| 78 cls.#typeNameProperty = cls.name; // Needed for RTI. | 108 cls.#typeNameProperty = cls.name; // Needed for RTI. |
| 79 cls.prototype.constructor = cls; | 109 cls.prototype.constructor = cls; |
| 80 cls.prototype[#operatorIsPrefix + cls.name] = cls; | 110 cls.prototype[#operatorIsPrefix + cls.name] = cls; |
| 81 | 111 |
| 82 // The superclass is only null for the Dart Object. | 112 // The superclass is only null for the Dart Object. |
| 83 if (sup != null) { | 113 if (sup != null) { |
| 84 cls.prototype.__proto__ = sup.prototype; | 114 if (supportsDirectProtoAccess) { |
| 115 // Firefox doesn't like to update the prototypes, but when setting up | |
| 116 // the hierarchy chain it's ok. | |
| 117 cls.prototype.__proto__ = sup.prototype; | |
| 118 return; | |
| 119 } | |
| 120 var clsPrototype = Object.create(sup.prototype); | |
| 121 copyProperties(cls.prototype, clsPrototype); | |
| 122 cls.prototype = clsPrototype; | |
| 85 } | 123 } |
| 86 } | 124 } |
| 87 | 125 |
| 88 // Mixes in the properties of [mixin] into [cls]. | 126 // Mixes in the properties of [mixin] into [cls]. |
| 89 function mixin(cls, mixin) { | 127 function mixin(cls, mixin) { |
| 90 copyProperties(mixin.prototype, cls.prototype); | 128 copyProperties(mixin.prototype, cls.prototype); |
| 91 } | 129 } |
| 92 | 130 |
| 93 // Creates a lazy field. | 131 // Creates a lazy field. |
| 94 // | 132 // |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 // The runtime ensures that const-lists cannot be modified. | 164 // The runtime ensures that const-lists cannot be modified. |
| 127 function makeConstList(list) { | 165 function makeConstList(list) { |
| 128 // By assigning a function to the properties they become part of the | 166 // By assigning a function to the properties they become part of the |
| 129 // hidden class. The actual values of the fields don't matter, since we | 167 // hidden class. The actual values of the fields don't matter, since we |
| 130 // only check if they exist. | 168 // only check if they exist. |
| 131 list.immutable\$list = Array; | 169 list.immutable\$list = Array; |
| 132 list.fixed\$length = Array; | 170 list.fixed\$length = Array; |
| 133 return list; | 171 return list; |
| 134 } | 172 } |
| 135 | 173 |
| 174 function convertToFastObject(properties) { | |
| 175 // Create an instance that uses 'properties' as prototype. This should | |
| 176 // make 'properties' a fast object. | |
| 177 function t() {}; | |
| 178 t.prototype = properties; | |
| 179 new t(); | |
| 180 return properties; | |
| 181 } | |
| 182 | |
| 136 // This variable is used by the tearOffCode to guarantee unique functions per | 183 // This variable is used by the tearOffCode to guarantee unique functions per |
| 137 // tear-offs. | 184 // tear-offs. |
| 138 var functionCounter = 0; | 185 var functionCounter = 0; |
| 139 #tearOffCode; | 186 #tearOffCode; |
| 140 | 187 |
| 141 // Each deferred hunk comes with its own types which are added to the end | 188 // Each deferred hunk comes with its own types which are added to the end |
| 142 // of the types-array. | 189 // of the types-array. |
| 143 // The `funTypes` passed to the `installTearOff` function below is relative to | 190 // The `funTypes` passed to the `installTearOff` function below is relative to |
| 144 // the hunk the function comes from. The `typesOffset` variable encodes the | 191 // the hunk the function comes from. The `typesOffset` variable encodes the |
| 145 // offset at which the new types will be added. | 192 // offset at which the new types will be added. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 // This relies on the fact that types are added *after* the tear-offs have | 270 // This relies on the fact that types are added *after* the tear-offs have |
| 224 // been installed. The tear-off function uses the types-length to figure | 271 // been installed. The tear-off function uses the types-length to figure |
| 225 // out at which offset its types are located. If the types were added earlier | 272 // out at which offset its types are located. If the types were added earlier |
| 226 // the offset would be wrong. | 273 // the offset would be wrong. |
| 227 types.push.apply(types, newTypes); | 274 types.push.apply(types, newTypes); |
| 228 } | 275 } |
| 229 | 276 |
| 230 // Updates the given holder with the properties of the [newHolder]. | 277 // Updates the given holder with the properties of the [newHolder]. |
| 231 // This function is used when a deferred fragment is initialized. | 278 // This function is used when a deferred fragment is initialized. |
| 232 function updateHolder(holder, newHolder) { | 279 function updateHolder(holder, newHolder) { |
| 233 // TODO(floitsch): updating the prototype (instead of copying) is | 280 // Firefox doesn't like when important objects have their prototype chain |
| 234 // *horribly* inefficient in Firefox. There we should just copy the | 281 // updated. We therefore do this only on V8. |
| 235 // properties. | 282 if (isChrome) { |
| 236 var oldPrototype = holder.__proto__; | 283 var oldPrototype = holder.__proto__; |
| 237 newHolder.__proto__ = oldPrototype; | 284 newHolder.__proto__ = oldPrototype; |
| 238 holder.__proto__ = newHolder; | 285 holder.__proto__ = newHolder; |
| 286 } else { | |
| 287 copyProperties(newHolder, holder); | |
| 288 } | |
| 239 return holder; | 289 return holder; |
| 240 } | 290 } |
| 241 | 291 |
| 242 // Every deferred hunk (i.e. fragment) is a function that we can invoke to | 292 // Every deferred hunk (i.e. fragment) is a function that we can invoke to |
| 243 // initialize it. At this moment it contributes its data to the main hunk. | 293 // initialize it. At this moment it contributes its data to the main hunk. |
| 244 function initializeDeferredHunk(hunk) { | 294 function initializeDeferredHunk(hunk) { |
| 245 // Update the typesOffset for the next deferred library. | 295 // Update the typesOffset for the next deferred library. |
| 246 typesOffset = #embeddedTypes.length; | 296 typesOffset = #embeddedTypes.length; |
| 247 | 297 |
| 248 // TODO(floitsch): extend natives. | 298 // TODO(floitsch): extend natives. |
| 249 hunk(inherit, mixin, lazy, makeConstList, installTearOff, | 299 hunk(inherit, mixin, lazy, makeConstList, convertToFastObject, installTearOff, |
| 250 updateHolder, updateTypes, setOrUpdateInterceptorsByTag, | 300 setFunctionNamesIfNecessary, updateHolder, updateTypes, |
| 251 setOrUpdateLeafTags, | 301 setOrUpdateInterceptorsByTag, setOrUpdateLeafTags, |
| 252 #embeddedGlobalsObject, #holdersList, #staticState); | 302 #embeddedGlobalsObject, #holdersList, #staticState); |
| 253 } | 303 } |
| 254 | 304 |
| 255 // Returns the global with the given [name]. | 305 // Returns the global with the given [name]. |
| 256 function getGlobalFromName(name) { | 306 function getGlobalFromName(name) { |
| 257 // TODO(floitsch): we are running through all holders. Since negative | 307 // TODO(floitsch): we are running through all holders. Since negative |
| 258 // lookups are expensive we might need to improve this. | 308 // lookups are expensive we might need to improve this. |
| 259 // Relies on the fact that all names are unique across all holders. | 309 // Relies on the fact that all names are unique across all holders. |
| 260 for (var i = 0; i < holders.length; i++) { | 310 for (var i = 0; i < holders.length; i++) { |
| 261 // The constant holder reuses the same names. Therefore we must skip it. | 311 // The constant holder reuses the same names. Therefore we must skip it. |
| 262 if (holders[i] == #constantHolderReference) continue; | 312 if (holders[i] == #constantHolderReference) continue; |
| 263 // Relies on the fact that all variables are unique. | 313 // Relies on the fact that all variables are unique. |
| 264 if (holders[i][name]) return holders[i][name]; | 314 if (holders[i][name]) return holders[i][name]; |
| 265 } | 315 } |
| 266 } | 316 } |
| 267 | 317 |
| 268 // Creates the holders. | 318 // Creates the holders. |
| 269 #holders; | 319 #holders; |
| 270 // TODO(floitsch): if name is not set (for example in IE), run through all | 320 |
| 271 // functions and set the name. | 321 // If the name is not set on the functions, do it now. |
| 322 setFunctionNamesIfNecessary(#holdersList); | |
| 272 | 323 |
| 273 // TODO(floitsch): we should build this object as a literal. | 324 // TODO(floitsch): we should build this object as a literal. |
| 274 var #staticStateDeclaration = {}; | 325 var #staticStateDeclaration = {}; |
| 275 | 326 |
| 276 // Sets the prototypes of classes. | 327 // Sets the prototypes of classes. |
| 277 #prototypes; | 328 #prototypes; |
| 278 // Sets aliases of methods (on the prototypes of classes). | 329 // Sets aliases of methods (on the prototypes of classes). |
| 279 #aliases; | 330 #aliases; |
| 280 // Installs the tear-offs of functions. | 331 // Installs the tear-offs of functions. |
| 281 #tearOffs; | 332 #tearOffs; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 300 #invokeMain; | 351 #invokeMain; |
| 301 })(); | 352 })(); |
| 302 }'''; | 353 }'''; |
| 303 | 354 |
| 304 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment. | 355 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment. |
| 305 /// | 356 /// |
| 306 /// However, at specific moments they need to contribute their data. | 357 /// However, at specific moments they need to contribute their data. |
| 307 /// For example, once the holders have been created, they are included into | 358 /// For example, once the holders have been created, they are included into |
| 308 /// the main holders. | 359 /// the main holders. |
| 309 const String deferredBoilerplate = ''' | 360 const String deferredBoilerplate = ''' |
| 310 function(inherit, mixin, lazy, makeConstList, installTearOff, | 361 function(inherit, mixin, lazy, makeConstList, convertToFastObject, |
| 311 updateHolder, updateTypes, | 362 installTearOff, setFunctionNamesIfNecessary, updateHolder, updateTypes, |
| 312 setOrUpdateInterceptorsByTag, setOrUpdateLeafTags, | 363 setOrUpdateInterceptorsByTag, setOrUpdateLeafTags, |
| 313 #embeddedGlobalsObject, holdersList, #staticState) { | 364 #embeddedGlobalsObject, holdersList, #staticState) { |
| 314 | 365 |
| 315 // Builds the holders. They only contain the data for new holders. | 366 // Builds the holders. They only contain the data for new holders. |
| 316 #holders; | 367 #holders; |
| 368 | |
| 369 // If the name is not set on the functions, do it now. | |
| 370 setFunctionNamesIfNecessary(#deferredHoldersList); | |
| 371 | |
| 317 // Updates the holders of the main-fragment. Uses the provided holdersList to | 372 // Updates the holders of the main-fragment. Uses the provided holdersList to |
| 318 // access the main holders. | 373 // access the main holders. |
| 319 // The local holders are replaced by the combined holders. This is necessary | 374 // The local holders are replaced by the combined holders. This is necessary |
| 320 // for the inheritance setup below. | 375 // for the inheritance setup below. |
| 321 #updateHolders; | 376 #updateHolders; |
| 322 // Sets the prototypes of the new classes. | 377 // Sets the prototypes of the new classes. |
| 323 #prototypes; | 378 #prototypes; |
| 324 // Sets aliases of methods (on the prototypes of classes). | 379 // Sets aliases of methods (on the prototypes of classes). |
| 325 #aliases; | 380 #aliases; |
| 326 // Installs the tear-offs of functions. | 381 // Installs the tear-offs of functions. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 369 | 424 |
| 370 js.Expression classReference(Class cls) { | 425 js.Expression classReference(Class cls) { |
| 371 return js.js('#.#', [cls.holder.name, cls.name]); | 426 return js.js('#.#', [cls.holder.name, cls.name]); |
| 372 } | 427 } |
| 373 | 428 |
| 374 js.Statement emitMainFragment( | 429 js.Statement emitMainFragment( |
| 375 Program program, | 430 Program program, |
| 376 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) { | 431 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) { |
| 377 MainFragment fragment = program.fragments.first; | 432 MainFragment fragment = program.fragments.first; |
| 378 | 433 |
| 434 Iterable<Holder> nonStaticStateHolders = program.holders | |
| 435 .where((Holder holder) => !holder.isStaticStateHolder); | |
| 436 | |
| 379 return js.js.statement(mainBoilerplate, | 437 return js.js.statement(mainBoilerplate, |
| 380 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), | 438 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), |
| 381 'typeNameProperty': js.string(ModelEmitter.typeNameProperty), | 439 'typeNameProperty': js.string(ModelEmitter.typeNameProperty), |
| 382 'cyclicThrow': backend.emitter.staticFunctionAccess( | 440 'cyclicThrow': backend.emitter.staticFunctionAccess( |
| 383 backend.getCyclicThrowHelper()), | 441 backend.getCyclicThrowHelper()), |
| 384 'operatorIsPrefix': js.string(namer.operatorIsPrefix), | 442 'operatorIsPrefix': js.string(namer.operatorIsPrefix), |
| 385 'tearOffCode': new js.Block(buildTearOffCode(backend)), | 443 'tearOffCode': new js.Block(buildTearOffCode(backend)), |
| 386 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES), | 444 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES), |
| 387 'embeddedInterceptorTags': | 445 'embeddedInterceptorTags': |
| 388 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG), | 446 generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG), |
| 389 'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS), | 447 'embeddedLeafTags': generateEmbeddedGlobalAccess(LEAF_TAGS), |
| 390 'embeddedGlobalsObject': js.js("init"), | 448 'embeddedGlobalsObject': js.js("init"), |
| 391 'holdersList': new js.ArrayInitializer(program.holders.map((holder) { | 449 'holdersList': new js.ArrayInitializer(nonStaticStateHolders |
| 392 return js.js("#", holder.name); | 450 .map((holder) => js.js("#", holder.name)) |
| 393 }).toList()), | 451 .toList(growable: false)), |
| 394 'staticStateDeclaration': new js.VariableDeclaration( | 452 'staticStateDeclaration': new js.VariableDeclaration( |
| 395 namer.staticStateHolder, allowRename: false), | 453 namer.staticStateHolder, allowRename: false), |
| 396 'staticState': js.js('#', namer.staticStateHolder), | 454 'staticState': js.js('#', namer.staticStateHolder), |
| 397 'constantHolderReference': buildConstantHolderReference(program), | 455 'constantHolderReference': buildConstantHolderReference(program), |
| 398 'holders': emitHolders(program.holders, fragment), | 456 'holders': emitHolders(program.holders, fragment), |
| 399 'callName': js.string(namer.callNameField), | 457 'callName': js.string(namer.callNameField), |
| 400 'argumentCount': js.string(namer.requiredParameterField), | 458 'argumentCount': js.string(namer.requiredParameterField), |
| 401 'defaultArgumentValues': js.string(namer.defaultValuesField), | 459 'defaultArgumentValues': js.string(namer.defaultValuesField), |
| 402 'prototypes': emitPrototypes(fragment), | 460 'prototypes': emitPrototypes(fragment), |
| 403 'inheritance': emitInheritance(fragment), | 461 'inheritance': emitInheritance(fragment), |
| 404 'aliases': emitInstanceMethodAliases(fragment), | 462 'aliases': emitInstanceMethodAliases(fragment), |
| 405 'tearOffs': emitInstallTearOffs(fragment), | 463 'tearOffs': emitInstallTearOffs(fragment), |
| 406 'constants': emitConstants(fragment), | 464 'constants': emitConstants(fragment), |
| 407 'staticNonFinalFields': emitStaticNonFinalFields(fragment), | 465 'staticNonFinalFields': emitStaticNonFinalFields(fragment), |
| 408 'lazyStatics': emitLazilyInitializedStatics(fragment), | 466 'lazyStatics': emitLazilyInitializedStatics(fragment), |
| 409 'embeddedGlobals': emitEmbeddedGlobals(program, deferredLoadHashes), | 467 'embeddedGlobals': emitEmbeddedGlobals(program, deferredLoadHashes), |
| 410 'nativeSupport': program.needsNativeSupport | 468 'nativeSupport': program.needsNativeSupport |
| 411 ? emitNativeSupport(fragment) | 469 ? emitNativeSupport(fragment) |
| 412 : new js.EmptyStatement(), | 470 : new js.EmptyStatement(), |
| 413 'invokeMain': fragment.invokeMain, | 471 'invokeMain': fragment.invokeMain, |
| 414 }); | 472 }); |
| 415 } | 473 } |
| 416 | 474 |
| 417 js.Expression emitDeferredFragment(DeferredFragment fragment, | 475 js.Expression emitDeferredFragment(DeferredFragment fragment, |
| 418 js.Expression deferredTypes, | 476 js.Expression deferredTypes, |
| 419 List<Holder> holders) { | 477 List<Holder> holders) { |
| 478 List<Holder> nonStaticStateHolders = holders | |
| 479 .where((Holder holder) => !holder.isStaticStateHolder) | |
| 480 .toList(growable: false); | |
| 481 | |
| 420 List<js.Statement> updateHolderAssignments = <js.Statement>[]; | 482 List<js.Statement> updateHolderAssignments = <js.Statement>[]; |
| 421 for (int i = 0; i < holders.length; i++) { | 483 for (int i = 0; i < nonStaticStateHolders.length; i++) { |
| 422 Holder holder = holders[i]; | 484 Holder holder = nonStaticStateHolders[i]; |
| 423 if (holder.isStaticStateHolder) continue; | |
| 424 updateHolderAssignments.add(js.js.statement( | 485 updateHolderAssignments.add(js.js.statement( |
| 425 '#holder = updateHolder(holdersList[#index], #holder)', | 486 '#holder = updateHolder(holdersList[#index], #holder)', |
| 426 {'index': js.number(i), | 487 {'index': js.number(i), |
| 427 'holder': new js.VariableUse(holder.name)})); | 488 'holder': new js.VariableUse(holder.name)})); |
| 428 } | 489 } |
| 429 | 490 |
| 430 // TODO(floitsch): if name is not set, run through all functions and set the | |
| 431 // name for IE. | |
| 432 // TODO(floitsch): don't just reference 'init'. | 491 // TODO(floitsch): don't just reference 'init'. |
| 433 return js.js(deferredBoilerplate, | 492 return js.js(deferredBoilerplate, |
| 434 {'embeddedGlobalsObject': new js.Parameter('init'), | 493 {'embeddedGlobalsObject': new js.Parameter('init'), |
| 435 'staticState': new js.Parameter(namer.staticStateHolder), | 494 'staticState': new js.Parameter(namer.staticStateHolder), |
| 436 'holders': emitHolders(holders, fragment), | 495 'holders': emitHolders(holders, fragment), |
| 496 'deferredHoldersList': new js.ArrayInitializer(nonStaticStateHolders | |
| 497 .map((holder) => js.js("#", holder.name)) | |
| 498 .toList(growable: false)), | |
| 437 'updateHolders': new js.Block(updateHolderAssignments), | 499 'updateHolders': new js.Block(updateHolderAssignments), |
| 438 'prototypes': emitPrototypes(fragment), | 500 'prototypes': emitPrototypes(fragment), |
| 439 'inheritance': emitInheritance(fragment), | 501 'inheritance': emitInheritance(fragment), |
| 440 'aliases': emitInstanceMethodAliases(fragment), | 502 'aliases': emitInstanceMethodAliases(fragment), |
| 441 'tearOffs': emitInstallTearOffs(fragment), | 503 'tearOffs': emitInstallTearOffs(fragment), |
| 442 'constants': emitConstants(fragment), | 504 'constants': emitConstants(fragment), |
| 443 'staticNonFinalFields': emitStaticNonFinalFields(fragment), | 505 'staticNonFinalFields': emitStaticNonFinalFields(fragment), |
| 444 'lazyStatics': emitLazilyInitializedStatics(fragment), | 506 'lazyStatics': emitLazilyInitializedStatics(fragment), |
| 445 'types': deferredTypes, | 507 'types': deferredTypes, |
| 446 // TODO(floitsch): only call emitNativeSupport if we need native. | 508 // TODO(floitsch): only call emitNativeSupport if we need native. |
| (...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1174 /// | 1236 /// |
| 1175 /// We don't try to reduce the size of the native data, but rather build | 1237 /// We don't try to reduce the size of the native data, but rather build |
| 1176 /// JavaScript object literals that contain all the information directly. | 1238 /// JavaScript object literals that contain all the information directly. |
| 1177 /// This means that the output size is bigger, but that the startup is faster. | 1239 /// This means that the output size is bigger, but that the startup is faster. |
| 1178 /// | 1240 /// |
| 1179 /// This function is the static equivalent of | 1241 /// This function is the static equivalent of |
| 1180 /// [NativeGenerator.buildNativeInfoHandler]. | 1242 /// [NativeGenerator.buildNativeInfoHandler]. |
| 1181 js.Statement emitNativeSupport(Fragment fragment) { | 1243 js.Statement emitNativeSupport(Fragment fragment) { |
| 1182 List<js.Statement> statements = <js.Statement>[]; | 1244 List<js.Statement> statements = <js.Statement>[]; |
| 1183 | 1245 |
| 1184 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { | 1246 // The isolate-affinity tag must only be initialized once per program. |
| 1247 if (fragment.isMainFragment && | |
| 1248 NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { | |
| 1185 statements.add(NativeGenerator.generateIsolateAffinityTagInitialization( | 1249 statements.add(NativeGenerator.generateIsolateAffinityTagInitialization( |
| 1186 backend, | 1250 backend, |
| 1187 generateEmbeddedGlobalAccess, | 1251 generateEmbeddedGlobalAccess, |
| 1188 // TODO(floitsch): convertToFastObject. (Needed for "interning" of | 1252 js.js(""" |
| 1189 // strings). | 1253 // On V8, the 'intern' function converts a string to a symbol, which |
|
Siggi Cherem (dart-lang)
2015/08/04 01:54:54
any reason why not define this as a function with
floitsch
2015/08/04 11:54:53
The copy is from a different emitter. We could cre
| |
| 1190 js.js("(function(x) { return x; })", []))); | 1254 // makes property access much faster. |
| 1255 function (s) { | |
| 1256 var o = {}; | |
| 1257 o[s] = 1; | |
| 1258 return Object.keys(convertToFastObject(o))[0]; | |
| 1259 }""", []))); | |
| 1191 } | 1260 } |
| 1192 | 1261 |
| 1193 Map<String, js.Expression> interceptorsByTag = <String, js.Expression>{}; | 1262 Map<String, js.Expression> interceptorsByTag = <String, js.Expression>{}; |
| 1194 Map<String, js.Expression> leafTags = <String, js.Expression>{}; | 1263 Map<String, js.Expression> leafTags = <String, js.Expression>{}; |
| 1195 js.Statement subclassAssignment = new js.EmptyStatement(); | 1264 js.Statement subclassAssignment = new js.EmptyStatement(); |
| 1196 | 1265 |
| 1197 for (Library library in fragment.libraries) { | 1266 for (Library library in fragment.libraries) { |
| 1198 for (Class cls in library.classes) { | 1267 for (Class cls in library.classes) { |
| 1199 if (cls.nativeLeafTags != null) { | 1268 if (cls.nativeLeafTags != null) { |
| 1200 for (String tag in cls.nativeLeafTags) { | 1269 for (String tag in cls.nativeLeafTags) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 1223 } | 1292 } |
| 1224 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", | 1293 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", |
| 1225 js.objectLiteral(interceptorsByTag))); | 1294 js.objectLiteral(interceptorsByTag))); |
| 1226 statements.add(js.js.statement("setOrUpdateLeafTags(#);", | 1295 statements.add(js.js.statement("setOrUpdateLeafTags(#);", |
| 1227 js.objectLiteral(leafTags))); | 1296 js.objectLiteral(leafTags))); |
| 1228 statements.add(subclassAssignment); | 1297 statements.add(subclassAssignment); |
| 1229 | 1298 |
| 1230 return new js.Block(statements); | 1299 return new js.Block(statements); |
| 1231 } | 1300 } |
| 1232 } | 1301 } |
| OLD | NEW |