@@ -8764,133 +8764,161 @@ export class Compiler extends DiagnosticEmitter {
87648764 return this . compileInstantiate ( ctor , expression . args , constraints , expression ) ;
87658765 }
87668766
8767- /** Gets the compiled constructor of the specified class or generates one if none is present. */
8768- ensureConstructor (
8767+ private createConstructorInstance (
8768+ /** true mean this constructor is externally visible, need to handle memory allocation */
8769+ isExternallyVisible : bool ,
87698770 /** Class wanting a constructor. */
87708771 classInstance : Class ,
87718772 /** Report node. */
87728773 reportNode : Node
87738774 ) : Function {
8774- let instance = classInstance . constructorInstance ;
8775- if ( instance ) {
8776- // shortcut if already compiled
8777- if ( instance . is ( CommonFlags . Compiled ) ) return instance ;
8778- // do not attempt to compile if inlined anyway
8779- if ( ! instance . hasDecorator ( DecoratorFlags . Inline ) ) this . compileFunction ( instance ) ;
8775+ const name = isExternallyVisible ? CommonNames . constructor : CommonNames . raw_constructor ;
8776+ let instance : Function | null = null ;
8777+ // clone base constructor if a derived class. note that we cannot just
8778+ // call the base ctor since the derived class may have additional fields.
8779+ let baseClass = classInstance . base ;
8780+ let contextualTypeArguments = cloneMap ( classInstance . contextualTypeArguments ) ;
8781+ if ( baseClass ) {
8782+ let baseCtor = this . ensureConstructor ( baseClass , reportNode ) ;
8783+ this . checkFieldInitialization ( baseClass , reportNode ) ;
8784+ instance = new Function (
8785+ name ,
8786+ new FunctionPrototype (
8787+ name ,
8788+ classInstance ,
8789+ // declaration is important, i.e. to access optional parameter initializers
8790+ ( < FunctionDeclaration > baseCtor . declaration ) . clone ( )
8791+ ) ,
8792+ null ,
8793+ Signature . create (
8794+ this . program ,
8795+ baseCtor . signature . parameterTypes ,
8796+ classInstance . type ,
8797+ classInstance . type ,
8798+ baseCtor . signature . requiredParameters ,
8799+ baseCtor . signature . hasRest
8800+ ) ,
8801+ contextualTypeArguments
8802+ ) ;
8803+ // otherwise make a default constructor
87808804 } else {
8781- // clone base constructor if a derived class. note that we cannot just
8782- // call the base ctor since the derived class may have additional fields.
8783- let baseClass = classInstance . base ;
8784- let contextualTypeArguments = cloneMap ( classInstance . contextualTypeArguments ) ;
8785- if ( baseClass ) {
8786- let baseCtor = this . ensureConstructor ( baseClass , reportNode ) ;
8787- this . checkFieldInitialization ( baseClass , reportNode ) ;
8788- instance = new Function (
8789- CommonNames . constructor ,
8790- new FunctionPrototype (
8791- CommonNames . constructor ,
8792- classInstance ,
8793- // declaration is important, i.e. to access optional parameter initializers
8794- ( < FunctionDeclaration > baseCtor . declaration ) . clone ( )
8795- ) ,
8796- null ,
8797- Signature . create (
8798- this . program ,
8799- baseCtor . signature . parameterTypes ,
8800- classInstance . type ,
8801- classInstance . type ,
8802- baseCtor . signature . requiredParameters ,
8803- baseCtor . signature . hasRest
8804- ) ,
8805- contextualTypeArguments
8806- ) ;
8807-
8808- // otherwise make a default constructor
8809- } else {
8810- instance = new Function (
8811- CommonNames . constructor ,
8812- new FunctionPrototype (
8813- CommonNames . constructor ,
8814- classInstance , // bound
8815- this . program . makeNativeFunctionDeclaration ( CommonNames . constructor ,
8816- CommonFlags . Instance | CommonFlags . Constructor
8817- )
8818- ) ,
8819- null ,
8820- Signature . create ( this . program , [ ] , classInstance . type , classInstance . type ) ,
8821- contextualTypeArguments
8822- ) ;
8823- }
8805+ instance = new Function (
8806+ name ,
8807+ new FunctionPrototype (
8808+ name ,
8809+ classInstance , // bound
8810+ this . program . makeNativeFunctionDeclaration ( name ,
8811+ CommonFlags . Instance | CommonFlags . Constructor
8812+ )
8813+ ) ,
8814+ null ,
8815+ Signature . create ( this . program , [ ] , classInstance . type , classInstance . type ) ,
8816+ contextualTypeArguments
8817+ ) ;
8818+ }
88248819
8825- instance . set ( CommonFlags . Compiled ) ;
8826- instance . prototype . setResolvedInstance ( "" , instance ) ;
8820+ instance . prototype . setResolvedInstance ( "" , instance ) ;
8821+ if ( isExternallyVisible ) {
88278822 if ( classInstance . is ( CommonFlags . ModuleExport ) ) {
88288823 instance . set ( CommonFlags . ModuleExport ) ;
88298824 }
8830- classInstance . constructorInstance = instance ;
88318825 let members = classInstance . members ;
88328826 if ( ! members ) classInstance . members = members = new Map ( ) ;
88338827 members . set ( CommonNames . constructor , instance . prototype ) ;
8828+ }
8829+ return instance ;
8830+ }
88348831
8835- let previousFlow = this . currentFlow ;
8836- let flow = instance . flow ;
8837- this . currentFlow = flow ;
8832+ private compileConstructorInstance (
8833+ isExternallyVisible : bool ,
8834+ instance : Function ,
8835+ classInstance : Class ,
8836+ reportNode : Node
8837+ ) : void {
8838+ instance . set ( CommonFlags . Compiled ) ;
8839+ let baseClass = classInstance . base ;
8840+ let previousFlow = this . currentFlow ;
8841+ let flow = instance . flow ;
8842+ this . currentFlow = flow ;
88388843
8839- // generate body
8840- let signature = instance . signature ;
8841- let module = this . module ;
8842- let sizeTypeRef = this . options . sizeTypeRef ;
8843- let stmts = new Array < ExpressionRef > ( ) ;
8844+ // generate body
8845+ let signature = instance . signature ;
8846+ let module = this . module ;
8847+ let sizeTypeRef = this . options . sizeTypeRef ;
8848+ let stmts = new Array < ExpressionRef > ( ) ;
88448849
8845- // {
8846- // this = <COND_ALLOC>
8847- // IF_DERIVED: this = super(this, ...args)
8848- // this.a = X
8849- // this.b = Y
8850- // return this
8851- // }
8852- stmts . push (
8853- this . makeConditionalAllocation ( classInstance , 0 )
8854- ) ;
8855- if ( baseClass ) {
8856- let parameterTypes = signature . parameterTypes ;
8857- let numParameters = parameterTypes . length ;
8858- let operands = new Array < ExpressionRef > ( 1 + numParameters ) ;
8859- operands [ 0 ] = module . local_get ( 0 , sizeTypeRef ) ;
8860- for ( let i = 1 ; i <= numParameters ; ++ i ) {
8861- operands [ i ] = module . local_get ( i , parameterTypes [ i - 1 ] . toRef ( ) ) ;
8862- }
8863- stmts . push (
8864- module . local_set ( 0 ,
8865- this . makeCallDirect ( assert ( baseClass . constructorInstance ) , operands , reportNode , false ) ,
8866- baseClass . type . isManaged
8867- )
8868- ) ;
8850+ // {
8851+ // this = <COND_ALLOC>?
8852+ // IF_DERIVED: this = super(this, ...args)
8853+ // this.a = X
8854+ // this.b = Y
8855+ // return this
8856+ // }
8857+ if ( isExternallyVisible ) {
8858+ stmts . push ( this . makeConditionalAllocation ( classInstance , 0 ) ) ;
8859+ }
8860+ if ( baseClass ) {
8861+ let parameterTypes = signature . parameterTypes ;
8862+ let numParameters = parameterTypes . length ;
8863+ let forwardCallOperands = new Array < ExpressionRef > ( 1 + numParameters ) ;
8864+ forwardCallOperands [ 0 ] = module . local_get ( 0 , sizeTypeRef ) ;
8865+ for ( let i = 1 ; i <= numParameters ; ++ i ) {
8866+ forwardCallOperands [ i ] = module . local_get ( i , parameterTypes [ i - 1 ] . toRef ( ) ) ;
88698867 }
8870- this . makeFieldInitializationInConstructor ( classInstance , stmts ) ;
8868+ let baseCallConstructorInstance = baseClass . rawConstructorInstance ;
8869+ if ( baseCallConstructorInstance == null ) baseCallConstructorInstance = assert ( baseClass . constructorInstance ) ;
88718870 stmts . push (
8872- module . local_get ( 0 , sizeTypeRef )
8871+ module . local_set (
8872+ 0 ,
8873+ this . makeCallDirect ( baseCallConstructorInstance , forwardCallOperands , reportNode , false ) ,
8874+ baseClass . type . isManaged
8875+ )
88738876 ) ;
8874- this . currentFlow = previousFlow ;
8877+ }
8878+ this . makeFieldInitializationInConstructor ( classInstance , stmts ) ;
8879+ stmts . push ( module . local_get ( 0 , sizeTypeRef ) ) ;
8880+ this . currentFlow = previousFlow ;
88758881
8876- // make the function
8877- let locals = instance . localsByIndex ;
8878- let varTypes = new Array < TypeRef > ( ) ; // of temp. vars added while compiling initializers
8879- let numOperands = 1 + signature . parameterTypes . length ;
8880- let numLocals = locals . length ;
8881- if ( numLocals > numOperands ) {
8882- for ( let i = numOperands ; i < numLocals ; ++ i ) varTypes . push ( locals [ i ] . type . toRef ( ) ) ;
8883- }
8884- let funcRef = module . addFunction (
8885- instance . internalName ,
8886- signature . paramRefs ,
8887- signature . resultRefs ,
8888- varTypes ,
8889- module . flatten ( stmts , sizeTypeRef )
8890- ) ;
8891- instance . finalize ( module , funcRef ) ;
8882+ // make the function
8883+ let locals = instance . localsByIndex ;
8884+ let varTypes = new Array < TypeRef > ( ) ; // of temp. vars added while compiling initializers
8885+ let numOperands = 1 + signature . parameterTypes . length ;
8886+ let numLocals = locals . length ;
8887+ if ( numLocals > numOperands ) {
8888+ for ( let i = numOperands ; i < numLocals ; ++ i ) varTypes . push ( locals [ i ] . type . toRef ( ) ) ;
88928889 }
8890+ let funcRef = module . addFunction (
8891+ instance . internalName ,
8892+ signature . paramRefs ,
8893+ signature . resultRefs ,
8894+ varTypes ,
8895+ module . flatten ( stmts , sizeTypeRef )
8896+ ) ;
8897+ instance . finalize ( module , funcRef ) ;
8898+ }
88938899
8900+ /** Gets the compiled constructor of the specified class or generates one if none is present. */
8901+ ensureConstructor (
8902+ /** Class wanting a constructor. */
8903+ classInstance : Class ,
8904+ /** Report node. */
8905+ reportNode : Node
8906+ ) : Function {
8907+ let instance = classInstance . constructorInstance ;
8908+ if ( instance ) {
8909+ // shortcut if already compiled
8910+ if ( instance . is ( CommonFlags . Compiled ) ) return instance ;
8911+ // do not attempt to compile if inlined anyway
8912+ if ( ! instance . hasDecorator ( DecoratorFlags . Inline ) ) this . compileFunction ( instance ) ;
8913+ } else {
8914+ instance = classInstance . constructorInstance = this . createConstructorInstance ( true , classInstance , reportNode ) ;
8915+ // TODO: maybe we can remove this function when the classInstance is finalized?
8916+ if ( ! classInstance . hasDecorator ( DecoratorFlags . Final ) ) {
8917+ let rawInstance = classInstance . rawConstructorInstance = this . createConstructorInstance ( false , classInstance , reportNode ) ;
8918+ this . compileConstructorInstance ( false , rawInstance , classInstance , reportNode ) ;
8919+ }
8920+ this . compileConstructorInstance ( true , instance , classInstance , reportNode ) ;
8921+ }
88948922 return instance ;
88958923 }
88968924
0 commit comments