@@ -58,7 +58,8 @@ import {
5858 isConstExpressionNaN ,
5959 ensureType ,
6060 createType ,
61- getConstValueInteger
61+ getConstValueInteger ,
62+ isConstZero
6263} from "./module" ;
6364
6465import {
@@ -10118,6 +10119,13 @@ export class Compiler extends DiagnosticEmitter {
1011810119
1011910120 // === Specialized code generation ==============================================================
1012010121
10122+ /** Check if possible to optimize the active initialization away if it's zero */
10123+ canOptimizeZeroInitialization ( valueExpr : ExpressionRef ) : bool {
10124+ const runtime = this . options . runtime ;
10125+ // Memory will be filled with 0 on itcms.__new
10126+ return runtime == Runtime . Incremental ? isConstZero ( valueExpr ) : false ;
10127+ }
10128+
1012110129 /** Makes a constant zero of the specified type. */
1012210130 makeZero ( type : Type ) : ExpressionRef {
1012310131 let module = this . module ;
@@ -10465,6 +10473,7 @@ export class Compiler extends DiagnosticEmitter {
1046510473 let parameterIndex = fieldPrototype . parameterIndex ;
1046610474
1046710475 // Defer non-parameter fields until parameter fields are initialized
10476+ // Since non-parameter may depend on parameter fields
1046810477 if ( parameterIndex < 0 ) {
1046910478 if ( ! nonParameterFields ) nonParameterFields = new Array ( ) ;
1047010479 nonParameterFields . push ( property ) ;
@@ -10493,23 +10502,40 @@ export class Compiler extends DiagnosticEmitter {
1049310502
1049410503 // Initialize deferred non-parameter fields
1049510504 if ( nonParameterFields ) {
10505+ const unmanagedClass = classInstance . type . isUnmanaged ;
1049610506 for ( let i = 0 , k = nonParameterFields . length ; i < k ; ++ i ) {
1049710507 let field = unchecked ( nonParameterFields [ i ] ) ;
1049810508 let fieldType = field . type ;
1049910509 let fieldPrototype = field . prototype ;
1050010510 let initializerNode = fieldPrototype . initializerNode ;
1050110511 assert ( fieldPrototype . parameterIndex < 0 ) ;
1050210512 let setterInstance = assert ( field . setterInstance ) ;
10503- let expr = this . makeCallDirect ( setterInstance , [
10504- module . local_get ( thisLocalIndex , sizeTypeRef ) ,
10505- initializerNode // use initializer if present, otherwise initialize with zero
10506- ? this . compileExpression ( initializerNode , fieldType , Constraints . ConvImplicit )
10507- : this . makeZero ( fieldType )
10508- ] , field . identifierNode , true ) ;
10509- if ( this . currentType != Type . void ) { // in case
10510- expr = module . drop ( expr ) ;
10513+
10514+ if ( initializerNode ) {
10515+ const valueExpr : ExpressionRef = this . compileExpression ( initializerNode , fieldType , Constraints . ConvImplicit ) ;
10516+ if ( unmanagedClass || ! this . canOptimizeZeroInitialization ( valueExpr ) ) {
10517+ let expr = this . makeCallDirect ( setterInstance , [
10518+ module . local_get ( thisLocalIndex , sizeTypeRef ) ,
10519+ valueExpr
10520+ ] , field . identifierNode , true ) ;
10521+ if ( this . currentType != Type . void ) { // in case
10522+ expr = module . drop ( expr ) ;
10523+ }
10524+ stmts . push ( expr ) ;
10525+ }
10526+ } else {
10527+ if ( unmanagedClass || ( this . options . runtime != Runtime . Incremental ) ) {
10528+ let expr = this . makeCallDirect ( setterInstance , [
10529+ module . local_get ( thisLocalIndex , sizeTypeRef ) ,
10530+ // Create only when necessary since makeZero will allocte persistent memory by Binaryen.
10531+ this . makeZero ( fieldType )
10532+ ] , field . identifierNode , true ) ;
10533+ if ( this . currentType != Type . void ) { // in case
10534+ expr = module . drop ( expr ) ;
10535+ }
10536+ stmts . push ( expr ) ;
10537+ }
1051110538 }
10512- stmts . push ( expr ) ;
1051310539 }
1051410540 }
1051510541
0 commit comments