mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Bug 1263490 - Part 3: Inline GetFirstDollarIndex intrinsic. r=h4writer
This commit is contained in:
parent
43419eb79b
commit
277f2f707b
@ -2213,6 +2213,63 @@ CodeGenerator::visitOutOfLineRegExpInstanceOptimizable(OutOfLineRegExpInstanceOp
|
||||
masm.jump(ool->rejoin());
|
||||
}
|
||||
|
||||
static void
|
||||
FindFirstDollarIndex(MacroAssembler& masm, Register str, Register len, Register chars,
|
||||
Register temp, Register output, bool isLatin1)
|
||||
{
|
||||
masm.loadStringChars(str, chars);
|
||||
|
||||
masm.move32(Imm32(0), output);
|
||||
|
||||
Label start, done;
|
||||
masm.bind(&start);
|
||||
if (isLatin1)
|
||||
masm.load8ZeroExtend(BaseIndex(chars, output, TimesOne), temp);
|
||||
else
|
||||
masm.load16ZeroExtend(BaseIndex(chars, output, TimesTwo), temp);
|
||||
|
||||
masm.branch32(Assembler::Equal, temp, Imm32('$'), &done);
|
||||
|
||||
masm.add32(Imm32(1), output);
|
||||
masm.branch32(Assembler::NotEqual, output, len, &start);
|
||||
|
||||
masm.move32(Imm32(-1), output);
|
||||
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
typedef bool (*GetFirstDollarIndexRawFn)(JSContext*, HandleString, int32_t*);
|
||||
static const VMFunction GetFirstDollarIndexRawInfo = FunctionInfo<GetFirstDollarIndexRawFn>(GetFirstDollarIndexRaw);
|
||||
|
||||
void
|
||||
CodeGenerator::visitGetFirstDollarIndex(LGetFirstDollarIndex* ins)
|
||||
{
|
||||
Register str = ToRegister(ins->str());
|
||||
Register output = ToRegister(ins->output());
|
||||
Register temp0 = ToRegister(ins->temp0());
|
||||
Register temp1 = ToRegister(ins->temp1());
|
||||
Register len = ToRegister(ins->temp2());
|
||||
|
||||
OutOfLineCode* ool = oolCallVM(GetFirstDollarIndexRawInfo, ins, ArgList(str),
|
||||
StoreRegisterTo(output));
|
||||
|
||||
masm.branchIfRope(str, ool->entry());
|
||||
masm.loadStringLength(str, len);
|
||||
|
||||
Label isLatin1, done;
|
||||
masm.branchLatin1String(str, &isLatin1);
|
||||
{
|
||||
FindFirstDollarIndex(masm, str, len, temp0, temp1, output, /* isLatin1 = */ false);
|
||||
}
|
||||
masm.jump(&done);
|
||||
{
|
||||
masm.bind(&isLatin1);
|
||||
FindFirstDollarIndex(masm, str, len, temp0, temp1, output, /* isLatin1 = */ true);
|
||||
}
|
||||
masm.bind(&done);
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
typedef JSString* (*StringReplaceFn)(JSContext*, HandleString, HandleString, HandleString);
|
||||
static const VMFunction StringFlatReplaceInfo = FunctionInfo<StringReplaceFn>(js::str_flat_replace_string);
|
||||
static const VMFunction StringReplaceInfo = FunctionInfo<StringReplaceFn>(StringReplace);
|
||||
|
@ -122,6 +122,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
void visitOutOfLineRegExpPrototypeOptimizable(OutOfLineRegExpPrototypeOptimizable* ool);
|
||||
void visitRegExpInstanceOptimizable(LRegExpInstanceOptimizable* lir);
|
||||
void visitOutOfLineRegExpInstanceOptimizable(OutOfLineRegExpInstanceOptimizable* ool);
|
||||
void visitGetFirstDollarIndex(LGetFirstDollarIndex* lir);
|
||||
void visitStringReplace(LStringReplace* lir);
|
||||
void emitSharedStub(ICStub::Kind kind, LInstruction* lir);
|
||||
void visitBinarySharedStub(LBinarySharedStub* lir);
|
||||
|
@ -70,6 +70,7 @@
|
||||
_(IsRegExpObject) \
|
||||
_(RegExpPrototypeOptimizable) \
|
||||
_(RegExpInstanceOptimizable) \
|
||||
_(GetFirstDollarIndex) \
|
||||
\
|
||||
_(String) \
|
||||
_(StringCharCodeAt) \
|
||||
|
@ -842,6 +842,7 @@ class IonBuilder
|
||||
InliningStatus inlineIsRegExpObject(CallInfo& callInfo);
|
||||
InliningStatus inlineRegExpPrototypeOptimizable(CallInfo& callInfo);
|
||||
InliningStatus inlineRegExpInstanceOptimizable(CallInfo& callInfo);
|
||||
InliningStatus inlineGetFirstDollarIndex(CallInfo& callInfo);
|
||||
|
||||
// Object natives and intrinsics.
|
||||
InliningStatus inlineObjectCreate(CallInfo& callInfo);
|
||||
|
@ -2315,6 +2315,17 @@ LIRGenerator::visitRegExpInstanceOptimizable(MRegExpInstanceOptimizable* ins)
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitGetFirstDollarIndex(MGetFirstDollarIndex* ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->str()->type() == MIRType_String);
|
||||
MOZ_ASSERT(ins->type() == MIRType_Int32);
|
||||
LGetFirstDollarIndex* lir = new(alloc()) LGetFirstDollarIndex(useRegister(ins->str()),
|
||||
temp(), temp(), temp());
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitStringReplace(MStringReplace* ins)
|
||||
{
|
||||
|
@ -168,6 +168,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
void visitRegExpTester(MRegExpTester* ins);
|
||||
void visitRegExpPrototypeOptimizable(MRegExpPrototypeOptimizable* ins);
|
||||
void visitRegExpInstanceOptimizable(MRegExpInstanceOptimizable* ins);
|
||||
void visitGetFirstDollarIndex(MGetFirstDollarIndex* ins);
|
||||
void visitStringReplace(MStringReplace* ins);
|
||||
void visitBinarySharedStub(MBinarySharedStub* ins);
|
||||
void visitUnarySharedStub(MUnarySharedStub* ins);
|
||||
|
@ -188,6 +188,8 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
||||
return inlineRegExpPrototypeOptimizable(callInfo);
|
||||
case InlinableNative::RegExpInstanceOptimizable:
|
||||
return inlineRegExpInstanceOptimizable(callInfo);
|
||||
case InlinableNative::GetFirstDollarIndex:
|
||||
return inlineGetFirstDollarIndex(callInfo);
|
||||
|
||||
// String natives.
|
||||
case InlinableNative::String:
|
||||
@ -1952,6 +1954,31 @@ IonBuilder::inlineRegExpInstanceOptimizable(CallInfo& callInfo)
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineGetFirstDollarIndex(CallInfo& callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 1 || callInfo.constructing()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* strArg = callInfo.getArg(0);
|
||||
|
||||
if (strArg->type() != MIRType_String)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (getInlineReturnType() != MIRType_Int32)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MInstruction* ins = MGetFirstDollarIndex::New(alloc(), strArg);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineStringReplaceString(CallInfo& callInfo)
|
||||
{
|
||||
|
@ -8099,6 +8099,31 @@ class MRegExpInstanceOptimizable
|
||||
}
|
||||
};
|
||||
|
||||
class MGetFirstDollarIndex
|
||||
: public MUnaryInstruction,
|
||||
public StringPolicy<0>::Data
|
||||
{
|
||||
explicit MGetFirstDollarIndex(MDefinition* str)
|
||||
: MUnaryInstruction(str)
|
||||
{
|
||||
setResultType(MIRType_Int32);
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(GetFirstDollarIndex)
|
||||
|
||||
static MGetFirstDollarIndex* New(TempAllocator& alloc, MDefinition* str) {
|
||||
return new(alloc) MGetFirstDollarIndex(str);
|
||||
}
|
||||
MDefinition* str() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
class MStringReplace
|
||||
: public MTernaryInstruction,
|
||||
public Mix3Policy<StringPolicy<0>, StringPolicy<1>, StringPolicy<2> >::Data
|
||||
|
@ -151,6 +151,7 @@ namespace jit {
|
||||
_(RegExpTester) \
|
||||
_(RegExpPrototypeOptimizable) \
|
||||
_(RegExpInstanceOptimizable) \
|
||||
_(GetFirstDollarIndex) \
|
||||
_(StringReplace) \
|
||||
_(Lambda) \
|
||||
_(LambdaArrow) \
|
||||
|
@ -4439,6 +4439,32 @@ class LRegExpInstanceOptimizable : public LInstructionHelper<1, 2, 1>
|
||||
}
|
||||
};
|
||||
|
||||
class LGetFirstDollarIndex : public LInstructionHelper<1, 1, 3>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(GetFirstDollarIndex);
|
||||
explicit LGetFirstDollarIndex(const LAllocation& str, const LDefinition& temp0,
|
||||
const LDefinition& temp1, const LDefinition& temp2) {
|
||||
setOperand(0, str);
|
||||
setTemp(0, temp0);
|
||||
setTemp(1, temp1);
|
||||
setTemp(2, temp2);
|
||||
}
|
||||
|
||||
const LAllocation* str() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LDefinition* temp0() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const LDefinition* temp1() {
|
||||
return getTemp(1);
|
||||
}
|
||||
const LDefinition* temp2() {
|
||||
return getTemp(2);
|
||||
}
|
||||
};
|
||||
|
||||
class LStringReplace: public LCallInstructionHelper<1, 3, 0>
|
||||
{
|
||||
public:
|
||||
|
@ -211,6 +211,7 @@
|
||||
_(RegExpTester) \
|
||||
_(RegExpPrototypeOptimizable) \
|
||||
_(RegExpInstanceOptimizable) \
|
||||
_(GetFirstDollarIndex) \
|
||||
_(StringReplace) \
|
||||
_(Substr) \
|
||||
_(BinarySharedStub) \
|
||||
|
@ -2568,7 +2568,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
||||
JS_FN("RegExpEscapeMetaChars", intrinsic_RegExpEscapeMetaChars, 1,0),
|
||||
JS_FN("GetElemBaseForLambda", intrinsic_GetElemBaseForLambda, 1,0),
|
||||
JS_FN("GetStringDataProperty", intrinsic_GetStringDataProperty, 2,0),
|
||||
JS_FN("GetFirstDollarIndex", GetFirstDollarIndex, 1,0),
|
||||
JS_INLINABLE_FN("GetFirstDollarIndex", GetFirstDollarIndex, 1,0,
|
||||
GetFirstDollarIndex),
|
||||
|
||||
JS_FN("FlatStringMatch", FlatStringMatch, 2,0),
|
||||
JS_FN("FlatStringSearch", FlatStringSearch, 2,0),
|
||||
|
Loading…
Reference in New Issue
Block a user