зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1641297 - Optimize Array.isArray in CacheIR and Warp. r=iain
Differential Revision: https://phabricator.services.mozilla.com/D77125
This commit is contained in:
Родитель
87e713f0c9
Коммит
41946bdc30
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -665,6 +665,12 @@
|
|||
args:
|
||||
obj: ObjId
|
||||
|
||||
- name: IsArrayResult
|
||||
shared: false
|
||||
transpile: true
|
||||
args:
|
||||
input: ValId
|
||||
|
||||
- name: IsObjectResult
|
||||
shared: true
|
||||
transpile: true
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче