Bug 1263490 - Part 3: Inline GetFirstDollarIndex intrinsic. r=h4writer

This commit is contained in:
Tooru Fujisawa 2016-04-26 03:37:50 +09:00
Родитель 43419eb79b
Коммит 277f2f707b
12 изменённых файлов: 154 добавлений и 1 удалений

Просмотреть файл

@ -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),