@@ -8764,133 +8764,161 @@ export class Compiler extends DiagnosticEmitter {
8764
8764
return this . compileInstantiate ( ctor , expression . args , constraints , expression ) ;
8765
8765
}
8766
8766
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 ,
8769
8770
/** Class wanting a constructor. */
8770
8771
classInstance : Class ,
8771
8772
/** Report node. */
8772
8773
reportNode : Node
8773
8774
) : 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
8780
8804
} 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
+ }
8824
8819
8825
- instance . set ( CommonFlags . Compiled ) ;
8826
- instance . prototype . setResolvedInstance ( "" , instance ) ;
8820
+ instance . prototype . setResolvedInstance ( "" , instance ) ;
8821
+ if ( isExternallyVisible ) {
8827
8822
if ( classInstance . is ( CommonFlags . ModuleExport ) ) {
8828
8823
instance . set ( CommonFlags . ModuleExport ) ;
8829
8824
}
8830
- classInstance . constructorInstance = instance ;
8831
8825
let members = classInstance . members ;
8832
8826
if ( ! members ) classInstance . members = members = new Map ( ) ;
8833
8827
members . set ( CommonNames . constructor , instance . prototype ) ;
8828
+ }
8829
+ return instance ;
8830
+ }
8834
8831
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 ;
8838
8843
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 > ( ) ;
8844
8849
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 ( ) ) ;
8869
8867
}
8870
- this . makeFieldInitializationInConstructor ( classInstance , stmts ) ;
8868
+ let baseCallConstructorInstance = baseClass . rawConstructorInstance ;
8869
+ if ( baseCallConstructorInstance == null ) baseCallConstructorInstance = assert ( baseClass . constructorInstance ) ;
8871
8870
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
+ )
8873
8876
) ;
8874
- this . currentFlow = previousFlow ;
8877
+ }
8878
+ this . makeFieldInitializationInConstructor ( classInstance , stmts ) ;
8879
+ stmts . push ( module . local_get ( 0 , sizeTypeRef ) ) ;
8880
+ this . currentFlow = previousFlow ;
8875
8881
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 ( ) ) ;
8892
8889
}
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
+ }
8893
8899
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
+ }
8894
8922
return instance ;
8895
8923
}
8896
8924
0 commit comments