@@ -4507,7 +4507,7 @@ export class Compiler extends DiagnosticEmitter {
45074507 case Token . Bar_Equals : {
45084508 let cacheContext : CompoundAssignmentCacheContext | null = null ;
45094509 let cacheTarget = this . getCompoundAssignmentSideEffectCacheTarget ( left ) ;
4510- if ( cacheTarget && this . needsCompoundAssignmentSideEffectCache ( left ) ) {
4510+ if ( cacheTarget && this . needsCompoundAssignmentSideEffectCache ( cacheTarget ) ) {
45114511 cacheContext = this . prepareCompoundAssignmentCache ( cacheTarget , contextualType . intType ) ;
45124512 if ( ! cacheContext ) return module . unreachable ( ) ;
45134513 leftExpr = cacheContext . leftExpr ;
@@ -4915,68 +4915,55 @@ export class Compiler extends DiagnosticEmitter {
49154915 let assignmentElementExpression : Expression | null = null ;
49164916 let assignmentThisExpr : ExpressionRef = 0 ;
49174917 let assignmentElementExpr : ExpressionRef = 0 ;
4918+ let cachedThisLocal : Local | null = null ;
4919+ let cachedThisType : Type = Type . void ;
4920+ let cachedElementLocal : Local | null = null ;
4921+ let cachedElementType : Type = Type . void ;
49184922 let readThisExpression : Expression | null = null ;
49194923 let readElementExpression : Expression | null = null ;
49204924
49214925 if ( cacheTarget . kind == NodeKind . PropertyAccess ) {
49224926 let access = < PropertyAccessExpression > cacheTarget ;
49234927 let receiverExpression = access . expression ;
4928+ assignmentThisExpression = receiverExpression ;
49244929 let receiverExpr = this . compileExpression ( receiverExpression , Type . auto ) ;
49254930 let receiverType = this . currentType ;
49264931 let receiverTemp = flow . getTempLocal ( receiverType ) ;
4932+ cachedThisLocal = receiverTemp ;
4933+ cachedThisType = receiverType ;
49274934 flow . setLocalFlag ( receiverTemp . index , LocalFlags . Initialized ) ;
49284935 setupPrefixExprs = [ module . local_set ( receiverTemp . index , receiverExpr , receiverType . isManaged ) ] ;
4929- let receiverCachedExpression = Node . createCompiledExpression (
4930- module . local_get ( receiverTemp . index , receiverType . toRef ( ) ) ,
4931- receiverType ,
4932- receiverExpression . range
4933- ) ;
4934- readThisExpression = receiverCachedExpression ;
4935- assignmentThisExpression = receiverCachedExpression ;
49364936 } else {
49374937 let access = < ElementAccessExpression > cacheTarget ;
49384938 let receiverExpression = access . expression ;
49394939 let elementExpression = access . elementExpression ;
4940- let receiverForRead : Expression = receiverExpression ;
4941- let elementForRead : Expression = elementExpression ;
49424940
4941+ readThisExpression = receiverExpression ;
4942+ readElementExpression = elementExpression ;
49434943 assignmentThisExpression = receiverExpression ;
49444944 assignmentElementExpression = elementExpression ;
49454945
49464946 if ( this . expressionHasSideEffects ( receiverExpression ) ) {
49474947 let receiverExpr = this . compileExpression ( receiverExpression , Type . auto ) ;
49484948 let receiverType = this . currentType ;
49494949 let receiverTemp = flow . getTempLocal ( receiverType ) ;
4950+ cachedThisLocal = receiverTemp ;
4951+ cachedThisType = receiverType ;
49504952 flow . setLocalFlag ( receiverTemp . index , LocalFlags . Initialized ) ;
49514953 if ( ! setupPrefixExprs ) setupPrefixExprs = [ ] ;
49524954 setupPrefixExprs . push ( module . local_set ( receiverTemp . index , receiverExpr , receiverType . isManaged ) ) ;
4953- let receiverCachedExpression = Node . createCompiledExpression (
4954- module . local_get ( receiverTemp . index , receiverType . toRef ( ) ) ,
4955- receiverType ,
4956- receiverExpression . range
4957- ) ;
4958- receiverForRead = receiverCachedExpression ;
4959- assignmentThisExpression = receiverCachedExpression ;
49604955 }
49614956
49624957 if ( this . expressionHasSideEffects ( elementExpression ) ) {
49634958 let elementExpr = this . compileExpression ( elementExpression , Type . auto ) ;
49644959 let elementType = this . currentType ;
49654960 let elementTemp = flow . getTempLocal ( elementType ) ;
4961+ cachedElementLocal = elementTemp ;
4962+ cachedElementType = elementType ;
49664963 flow . setLocalFlag ( elementTemp . index , LocalFlags . Initialized ) ;
49674964 if ( ! setupPrefixExprs ) setupPrefixExprs = [ ] ;
49684965 setupPrefixExprs . push ( module . local_set ( elementTemp . index , elementExpr , elementType . isManaged ) ) ;
4969- let elementCachedExpression = Node . createCompiledExpression (
4970- module . local_get ( elementTemp . index , elementType . toRef ( ) ) ,
4971- elementType ,
4972- elementExpression . range
4973- ) ;
4974- elementForRead = elementCachedExpression ;
4975- assignmentElementExpression = elementCachedExpression ;
49764966 }
4977-
4978- readThisExpression = receiverForRead ;
4979- readElementExpression = elementForRead ;
49804967 }
49814968
49824969 let leftExpr : ExpressionRef ;
@@ -4992,13 +4979,37 @@ export class Compiler extends DiagnosticEmitter {
49924979 let getterInstance = ( < Property > target ) . getterInstance ;
49934980 if ( ! getterInstance ) return null ;
49944981 if ( getterInstance . is ( CommonFlags . Instance ) ) {
4995- let thisArg = this . compileExpression (
4996- assert ( readThisExpression ) ,
4997- assert ( getterInstance . signature . thisType ) ,
4998- Constraints . ConvImplicit | Constraints . IsThis
4999- ) ;
5000- assignmentThisExpr = thisArg ;
5001- leftExpr = this . compileCallDirect ( getterInstance , [ ] , cacheTarget , thisArg ) ;
4982+ let thisType = assert ( getterInstance . signature . thisType ) ;
4983+ if ( cachedThisLocal ) {
4984+ let thisRef = cachedThisType . toRef ( ) ;
4985+ let thisArg = this . convertExpression (
4986+ module . local_get ( cachedThisLocal . index , thisRef ) ,
4987+ cachedThisType ,
4988+ thisType ,
4989+ false ,
4990+ cacheTarget
4991+ ) ;
4992+ assignmentThisExpr = this . convertExpression (
4993+ module . local_get ( cachedThisLocal . index , thisRef ) ,
4994+ cachedThisType ,
4995+ thisType ,
4996+ false ,
4997+ cacheTarget
4998+ ) ;
4999+ leftExpr = this . compileCallDirect ( getterInstance , [ ] , cacheTarget , thisArg ) ;
5000+ } else {
5001+ let thisArg = this . compileExpression (
5002+ assert ( readThisExpression ) ,
5003+ thisType ,
5004+ Constraints . ConvImplicit | Constraints . IsThis
5005+ ) ;
5006+ assignmentThisExpr = this . compileExpression (
5007+ assert ( assignmentThisExpression ) ,
5008+ thisType ,
5009+ Constraints . ConvImplicit | Constraints . IsThis
5010+ ) ;
5011+ leftExpr = this . compileCallDirect ( getterInstance , [ ] , cacheTarget , thisArg ) ;
5012+ }
50025013 } else {
50035014 leftExpr = this . compileCallDirect ( getterInstance , [ ] , cacheTarget ) ;
50045015 }
@@ -5019,18 +5030,66 @@ export class Compiler extends DiagnosticEmitter {
50195030 ) ;
50205031 return null ;
50215032 }
5022- let thisArg = this . compileExpression (
5023- assert ( readThisExpression ) ,
5024- classInstance . type ,
5025- Constraints . ConvImplicit | Constraints . IsThis
5026- ) ;
5027- let indexArg = this . compileExpression (
5028- assert ( readElementExpression ) ,
5029- getterInstance . signature . parameterTypes [ 0 ] ,
5030- Constraints . ConvImplicit
5031- ) ;
5032- assignmentThisExpr = thisArg ;
5033- assignmentElementExpr = indexArg ;
5033+ let thisType = classInstance . type ;
5034+ let thisArg : ExpressionRef ;
5035+ if ( cachedThisLocal ) {
5036+ let thisRef = cachedThisType . toRef ( ) ;
5037+ thisArg = this . convertExpression (
5038+ module . local_get ( cachedThisLocal . index , thisRef ) ,
5039+ cachedThisType ,
5040+ thisType ,
5041+ false ,
5042+ cacheTarget
5043+ ) ;
5044+ assignmentThisExpr = this . convertExpression (
5045+ module . local_get ( cachedThisLocal . index , thisRef ) ,
5046+ cachedThisType ,
5047+ thisType ,
5048+ false ,
5049+ cacheTarget
5050+ ) ;
5051+ } else {
5052+ thisArg = this . compileExpression (
5053+ assert ( readThisExpression ) ,
5054+ thisType ,
5055+ Constraints . ConvImplicit | Constraints . IsThis
5056+ ) ;
5057+ assignmentThisExpr = this . compileExpression (
5058+ assert ( assignmentThisExpression ) ,
5059+ thisType ,
5060+ Constraints . ConvImplicit | Constraints . IsThis
5061+ ) ;
5062+ }
5063+ let indexType = getterInstance . signature . parameterTypes [ 0 ] ;
5064+ let indexArg : ExpressionRef ;
5065+ if ( cachedElementLocal ) {
5066+ let elementRef = cachedElementType . toRef ( ) ;
5067+ indexArg = this . convertExpression (
5068+ module . local_get ( cachedElementLocal . index , elementRef ) ,
5069+ cachedElementType ,
5070+ indexType ,
5071+ false ,
5072+ cacheTarget
5073+ ) ;
5074+ assignmentElementExpr = this . convertExpression (
5075+ module . local_get ( cachedElementLocal . index , elementRef ) ,
5076+ cachedElementType ,
5077+ indexType ,
5078+ false ,
5079+ cacheTarget
5080+ ) ;
5081+ } else {
5082+ indexArg = this . compileExpression (
5083+ assert ( readElementExpression ) ,
5084+ indexType ,
5085+ Constraints . ConvImplicit
5086+ ) ;
5087+ assignmentElementExpr = this . compileExpression (
5088+ assert ( assignmentElementExpression ) ,
5089+ indexType ,
5090+ Constraints . ConvImplicit
5091+ ) ;
5092+ }
50345093 leftExpr = this . makeCallDirect ( getterInstance , [ thisArg , indexArg ] , cacheTarget ) ;
50355094 leftType = this . currentType ;
50365095 break ;
0 commit comments