@@ -2786,7 +2786,7 @@ const artQuickCodeReplacementTrampolineWriters = {
27862786 arm64 : writeArtQuickCodeReplacementTrampolineArm64
27872787} ;
27882788
2789- function writeArtQuickCodeReplacementTrampolineIA32 ( trampoline , target , redirectSize , vm ) {
2789+ function writeArtQuickCodeReplacementTrampolineIA32 ( trampoline , target , redirectSize , constraints , vm ) {
27902790 const threadOffsets = getArtThreadSpec ( vm ) . offset ;
27912791 const artMethodOffsets = getArtMethodSpec ( vm ) . offset ;
27922792
@@ -2849,7 +2849,7 @@ function writeArtQuickCodeReplacementTrampolineIA32 (trampoline, target, redirec
28492849 return offset ;
28502850}
28512851
2852- function writeArtQuickCodeReplacementTrampolineX64 ( trampoline , target , redirectSize , vm ) {
2852+ function writeArtQuickCodeReplacementTrampolineX64 ( trampoline , target , redirectSize , constraints , vm ) {
28532853 const threadOffsets = getArtThreadSpec ( vm ) . offset ;
28542854 const artMethodOffsets = getArtMethodSpec ( vm ) . offset ;
28552855
@@ -2912,7 +2912,7 @@ function writeArtQuickCodeReplacementTrampolineX64 (trampoline, target, redirect
29122912 return offset ;
29132913}
29142914
2915- function writeArtQuickCodeReplacementTrampolineArm ( trampoline , target , redirectSize , vm ) {
2915+ function writeArtQuickCodeReplacementTrampolineArm ( trampoline , target , redirectSize , constraints , vm ) {
29162916 const artMethodOffsets = getArtMethodSpec ( vm ) . offset ;
29172917
29182918 const targetAddress = target . and ( THUMB_BIT_REMOVAL_MASK ) ;
@@ -2999,7 +2999,7 @@ function writeArtQuickCodeReplacementTrampolineArm (trampoline, target, redirect
29992999 return offset ;
30003000}
30013001
3002- function writeArtQuickCodeReplacementTrampolineArm64 ( trampoline , target , redirectSize , vm ) {
3002+ function writeArtQuickCodeReplacementTrampolineArm64 ( trampoline , target , redirectSize , { availableScratchRegs } , vm ) {
30033003 const artMethodOffsets = getArtMethodSpec ( vm ) . offset ;
30043004
30053005 let offset ;
@@ -3068,8 +3068,9 @@ function writeArtQuickCodeReplacementTrampolineArm64 (trampoline, target, redire
30683068 relocator . writeAll ( ) ;
30693069
30703070 if ( ! relocator . eoi ) {
3071- writer . putLdrRegAddress ( 'x17' , target . add ( offset ) ) ;
3072- writer . putBrReg ( 'x17' ) ;
3071+ const scratchReg = Array . from ( availableScratchRegs ) [ 0 ] ;
3072+ writer . putLdrRegAddress ( scratchReg , target . add ( offset ) ) ;
3073+ writer . putBrReg ( scratchReg ) ;
30733074 }
30743075
30753076 writer . putLabel ( 'invoke_replacement' ) ;
@@ -3146,7 +3147,7 @@ class ArtQuickCodeInterceptor {
31463147 this . overwrittenPrologueLength = 0 ;
31473148 }
31483149
3149- _canRelocateCode ( relocationSize ) {
3150+ _canRelocateCode ( relocationSize , constraints ) {
31503151 const Writer = thunkWriters [ Process . arch ] ;
31513152 const Relocator = thunkRelocators [ Process . arch ] ;
31523153
@@ -3156,14 +3157,44 @@ class ArtQuickCodeInterceptor {
31563157 const relocator = new Relocator ( quickCodeAddress , writer ) ;
31573158
31583159 let offset ;
3159- do {
3160- offset = relocator . readOne ( ) ;
3161- } while ( offset < relocationSize && ! relocator . eoi ) ;
3160+ if ( Process . arch === 'arm64' ) {
3161+ let availableScratchRegs = new Set ( [ 'x16' , 'x17' ] ) ;
3162+
3163+ do {
3164+ const nextOffset = relocator . readOne ( ) ;
3165+
3166+ const nextScratchRegs = new Set ( availableScratchRegs ) ;
3167+ const { read, written } = relocator . input . regsAccessed ;
3168+ for ( const regs of [ read , written ] ) {
3169+ for ( const reg of regs ) {
3170+ let name ;
3171+ if ( reg . startsWith ( 'w' ) ) {
3172+ name = 'x' + reg . substring ( 1 ) ;
3173+ } else {
3174+ name = reg ;
3175+ }
3176+ nextScratchRegs . delete ( name ) ;
3177+ }
3178+ }
3179+ if ( nextScratchRegs . size === 0 ) {
3180+ break ;
3181+ }
3182+
3183+ offset = nextOffset ;
3184+ availableScratchRegs = nextScratchRegs ;
3185+ } while ( offset < relocationSize && ! relocator . eoi ) ;
3186+
3187+ constraints . availableScratchRegs = availableScratchRegs ;
3188+ } else {
3189+ do {
3190+ offset = relocator . readOne ( ) ;
3191+ } while ( offset < relocationSize && ! relocator . eoi ) ;
3192+ }
31623193
31633194 return offset >= relocationSize ;
31643195 }
31653196
3166- _createTrampoline ( ) {
3197+ _allocateTrampoline ( ) {
31673198 if ( trampolineAllocator === null ) {
31683199 const trampolineSize = ( pointerSize === 4 ) ? 128 : 256 ;
31693200 trampolineAllocator = makeCodeAllocator ( trampolineSize ) ;
@@ -3173,7 +3204,8 @@ class ArtQuickCodeInterceptor {
31733204
31743205 let redirectSize , spec ;
31753206 let alignment = 1 ;
3176- if ( pointerSize === 4 || this . _canRelocateCode ( maxRedirectSize ) ) {
3207+ const constraints = { } ;
3208+ if ( pointerSize === 4 || this . _canRelocateCode ( maxRedirectSize , constraints ) ) {
31773209 redirectSize = maxRedirectSize ;
31783210
31793211 spec = { } ;
@@ -3193,19 +3225,21 @@ class ArtQuickCodeInterceptor {
31933225
31943226 this . redirectSize = redirectSize ;
31953227 this . trampoline = trampolineAllocator . allocateSlice ( spec , alignment ) ;
3228+
3229+ return constraints ;
31963230 }
31973231
31983232 _destroyTrampoline ( ) {
31993233 trampolineAllocator . freeSlice ( this . trampoline ) ;
32003234 }
32013235
32023236 activate ( vm ) {
3203- this . _createTrampoline ( ) ;
3237+ const constraints = this . _allocateTrampoline ( ) ;
32043238
32053239 const { trampoline, quickCode, redirectSize } = this ;
32063240
32073241 const writeTrampoline = artQuickCodeReplacementTrampolineWriters [ Process . arch ] ;
3208- const prologueLength = writeTrampoline ( trampoline , quickCode , redirectSize , vm ) ;
3242+ const prologueLength = writeTrampoline ( trampoline , quickCode , redirectSize , constraints , vm ) ;
32093243 this . overwrittenPrologueLength = prologueLength ;
32103244
32113245 this . overwrittenPrologue = Memory . dup ( this . quickCodeAddress , prologueLength ) ;
0 commit comments