Skip to content

Commit d4d2a42

Browse files
committed
android: Fix IP0/IP1 register clobber on arm64
We need to determine which of these the ART quick code is using, picking the one unused, and also make sure we don't relocate code beyond the point where both registers are taken.
1 parent c87109d commit d4d2a42

File tree

1 file changed

+48
-14
lines changed

1 file changed

+48
-14
lines changed

lib/android.js

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)