Bug 1641297 - Optimize Array.isArray in CacheIR and Warp. r=iain

Differential Revision: https://phabricator.services.mozilla.com/D77125
This commit is contained in:
Tom Schuster 2020-05-28 09:35:18 +00:00
parent 87e713f0c9
commit 41946bdc30
6 changed files with 98 additions and 0 deletions

View File

@ -1437,6 +1437,56 @@ bool BaselineCacheIRCompiler::emitArrayPush(ObjOperandId objId,
return true;
}
bool BaselineCacheIRCompiler::emitIsArrayResult(ValOperandId inputId) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
AutoOutputRegister output(*this);
AutoScratchRegister scratch1(allocator, masm);
AutoScratchRegisterMaybeOutput scratch2(allocator, masm, output);
ValueOperand val = allocator.useValueRegister(masm, inputId);
allocator.discardStack(masm);
Label isNotArray;
// Primitives are never Arrays.
masm.branchTestObject(Assembler::NotEqual, val, &isNotArray);
masm.unboxObject(val, scratch1);
Label isArray;
masm.branchTestObjClass(Assembler::Equal, scratch1, &ArrayObject::class_,
scratch2, scratch1, &isArray);
// isArray can also return true for Proxy wrapped Arrays.
masm.branchTestObjectIsProxy(false, scratch1, scratch2, &isNotArray);
Label done;
{
AutoStubFrame stubFrame(*this);
stubFrame.enter(masm, scratch2);
masm.Push(scratch1);
using Fn = bool (*)(JSContext*, HandleObject, bool*);
callVM<Fn, js::IsArrayFromJit>(masm);
stubFrame.leave(masm);
masm.tagValue(JSVAL_TYPE_BOOLEAN, ReturnReg, output.valueReg());
masm.jump(&done);
}
masm.bind(&isNotArray);
masm.moveValue(BooleanValue(false), output.valueReg());
masm.jump(&done);
masm.bind(&isArray);
masm.moveValue(BooleanValue(true), output.valueReg());
masm.bind(&done);
return true;
}
bool BaselineCacheIRCompiler::emitCallNativeSetter(ObjOperandId objId,
uint32_t setterOffset,
ValOperandId rhsId) {

View File

@ -5000,6 +5000,31 @@ AttachDecision CallIRGenerator::tryAttachArrayJoin(HandleFunction callee) {
return AttachDecision::Attach;
}
AttachDecision CallIRGenerator::tryAttachArrayIsArray(HandleFunction callee) {
// Need a single argument.
if (argc_ != 1) {
return AttachDecision::NoAction;
}
// Initialize the input operand.
Int32OperandId argcId(writer.setInputOperandId(0));
// Guard callee is the 'isArray' intrinsic native function.
emitNativeCalleeGuard(callee);
// Check if the argument is an Array and return result.
ValOperandId argId = writer.loadArgumentFixedSlot(ArgumentKind::Arg0, argc_);
writer.isArrayResult(argId);
// This stub does not need to be monitored, because it always
// returns a boolean.
writer.returnFromIC();
cacheIRStubKind_ = BaselineCacheIRStubKind::Regular;
trackAttached("ArrayIsArray");
return AttachDecision::Attach;
}
AttachDecision CallIRGenerator::tryAttachIsSuspendedGenerator(
HandleFunction callee) {
// The IsSuspendedGenerator intrinsic is only called in
@ -5555,6 +5580,8 @@ AttachDecision CallIRGenerator::tryAttachInlinableNative(
return tryAttachArrayPush(callee);
case InlinableNative::ArrayJoin:
return tryAttachArrayJoin(callee);
case InlinableNative::ArrayIsArray:
return tryAttachArrayIsArray(callee);
// Intrinsics.
case InlinableNative::IntrinsicIsSuspendedGenerator:

View File

@ -1520,6 +1520,7 @@ class MOZ_RAII CallIRGenerator : public IRGenerator {
AttachDecision tryAttachArrayPush(HandleFunction callee);
AttachDecision tryAttachArrayJoin(HandleFunction callee);
AttachDecision tryAttachArrayIsArray(HandleFunction callee);
AttachDecision tryAttachIsSuspendedGenerator(HandleFunction callee);
AttachDecision tryAttachToString(HandleFunction callee);
AttachDecision tryAttachToObject(HandleFunction callee);

View File

@ -665,6 +665,12 @@
args:
obj: ObjId
- name: IsArrayResult
shared: false
transpile: true
args:
input: ValId
- name: IsObjectResult
shared: true
transpile: true

View File

@ -2418,3 +2418,7 @@ bool IonCacheIRCompiler::emitGuardFunApply(Int32OperandId argcId,
CallFlags flags) {
MOZ_CRASH("Call ICs not used in ion");
}
bool IonCacheIRCompiler::emitIsArrayResult(ValOperandId inputId) {
MOZ_CRASH("Call ICs not used in ion");
}

View File

@ -1100,6 +1100,16 @@ bool WarpCacheIRTranspiler::emitArrayPush(ObjOperandId objId,
return resumeAfter(ins);
}
bool WarpCacheIRTranspiler::emitIsArrayResult(ValOperandId inputId) {
MDefinition* value = getOperand(inputId);
auto* isArray = MIsArray::New(alloc(), value);
addEffectful(isArray);
pushResult(isArray);
return resumeAfter(isArray);
}
bool WarpCacheIRTranspiler::emitIsObjectResult(ValOperandId inputId) {
MDefinition* value = getOperand(inputId);