mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 951439 - Use CallVM for RegExp.exec(). r=h4writer
This commit is contained in:
parent
ec3329319a
commit
1b114e176d
@ -611,8 +611,8 @@ ExecuteRegExp(JSContext *cx, CallArgs args, MatchConduit &matches)
|
||||
|
||||
/* ES5 15.10.6.2. */
|
||||
static bool
|
||||
regexp_exec_impl(JSContext *cx, CallArgs args, HandleObject regexp, HandleString string,
|
||||
RegExpStaticsUpdate staticsUpdate)
|
||||
regexp_exec_impl(JSContext *cx, HandleObject regexp, HandleString string,
|
||||
RegExpStaticsUpdate staticsUpdate, MutableHandleValue rval)
|
||||
{
|
||||
/* Execute regular expression and gather matches. */
|
||||
ScopedMatchPairs matches(&cx->tempLifoAlloc());
|
||||
@ -624,11 +624,11 @@ regexp_exec_impl(JSContext *cx, CallArgs args, HandleObject regexp, HandleString
|
||||
return false;
|
||||
|
||||
if (status == RegExpRunStatus_Success_NotFound) {
|
||||
args.rval().setNull();
|
||||
rval.setNull();
|
||||
return true;
|
||||
}
|
||||
|
||||
return CreateRegExpMatchResult(cx, string, matches, args.rval());
|
||||
return CreateRegExpMatchResult(cx, string, matches, rval);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -639,7 +639,7 @@ regexp_exec_impl(JSContext *cx, CallArgs args)
|
||||
if (!string)
|
||||
return false;
|
||||
|
||||
return regexp_exec_impl(cx, args, regexp, string, UpdateRegExpStatics);
|
||||
return regexp_exec_impl(cx, regexp, string, UpdateRegExpStatics, args.rval());
|
||||
}
|
||||
|
||||
bool
|
||||
@ -649,6 +649,14 @@ js::regexp_exec(JSContext *cx, unsigned argc, Value *vp)
|
||||
return CallNonGenericMethod(cx, IsRegExp, regexp_exec_impl, args);
|
||||
}
|
||||
|
||||
/* Separate interface for use by IonMonkey. */
|
||||
bool
|
||||
js::regexp_exec_raw(JSContext *cx, HandleObject regexp, HandleString input, Value *vp)
|
||||
{
|
||||
MutableHandleValue vpHandle = MutableHandleValue::fromMarkedLocation(vp);
|
||||
return regexp_exec_impl(cx, regexp, input, UpdateRegExpStatics, vpHandle);
|
||||
}
|
||||
|
||||
bool
|
||||
js::regexp_exec_no_statics(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
@ -660,7 +668,7 @@ js::regexp_exec_no_statics(JSContext *cx, unsigned argc, Value *vp)
|
||||
RootedObject regexp(cx, &args[0].toObject());
|
||||
RootedString string(cx, args[1].toString());
|
||||
|
||||
return regexp_exec_impl(cx, args, regexp, string, DontUpdateRegExpStatics);
|
||||
return regexp_exec_impl(cx, regexp, string, DontUpdateRegExpStatics, args.rval());
|
||||
}
|
||||
|
||||
/* ES5 15.10.6.3. */
|
||||
|
@ -48,6 +48,9 @@ bool
|
||||
CreateRegExpMatchResult(JSContext *cx, HandleString input, const jschar *chars, size_t length,
|
||||
MatchPairs &matches, MutableHandleValue rval);
|
||||
|
||||
extern bool
|
||||
regexp_exec_raw(JSContext *cx, HandleObject regexp, HandleString input, Value *vp);
|
||||
|
||||
extern bool
|
||||
regexp_exec(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
|
@ -767,6 +767,18 @@ CodeGenerator::visitRegExp(LRegExp *lir)
|
||||
return callVM(CloneRegExpObjectInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool (*RegExpExecRawFn)(JSContext *cx, HandleObject regexp,
|
||||
HandleString input, Value *vp);
|
||||
static const VMFunction RegExpExecRawInfo = FunctionInfo<RegExpExecRawFn>(regexp_exec_raw);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitRegExpExec(LRegExpExec *lir)
|
||||
{
|
||||
pushArg(ToRegister(lir->string()));
|
||||
pushArg(ToRegister(lir->regexp()));
|
||||
return callVM(RegExpExecRawInfo, lir);
|
||||
}
|
||||
|
||||
typedef bool (*RegExpTestRawFn)(JSContext *cx, HandleObject regexp,
|
||||
HandleString input, bool *result);
|
||||
static const VMFunction RegExpTestRawInfo = FunctionInfo<RegExpTestRawFn>(regexp_test_raw);
|
||||
|
@ -90,6 +90,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitDoubleToString(LDoubleToString *lir);
|
||||
bool visitInteger(LInteger *lir);
|
||||
bool visitRegExp(LRegExp *lir);
|
||||
bool visitRegExpExec(LRegExpExec *lir);
|
||||
bool visitRegExpTest(LRegExpTest *lir);
|
||||
bool visitLambda(LLambda *lir);
|
||||
bool visitLambdaForSingleton(LLambdaForSingleton *lir);
|
||||
|
@ -630,6 +630,7 @@ class IonBuilder : public MIRGenerator
|
||||
InliningStatus inlineStrCharAt(CallInfo &callInfo);
|
||||
|
||||
// RegExp natives.
|
||||
InliningStatus inlineRegExpExec(CallInfo &callInfo);
|
||||
InliningStatus inlineRegExpTest(CallInfo &callInfo);
|
||||
|
||||
// Array intrinsics.
|
||||
|
@ -3215,6 +3215,29 @@ class LRegExp : public LCallInstructionHelper<1, 0, 0>
|
||||
}
|
||||
};
|
||||
|
||||
class LRegExpExec : public LCallInstructionHelper<1, 2, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(RegExpExec)
|
||||
|
||||
LRegExpExec(const LAllocation ®exp, const LAllocation &string)
|
||||
{
|
||||
setOperand(0, regexp);
|
||||
setOperand(1, string);
|
||||
}
|
||||
|
||||
const LAllocation *regexp() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LAllocation *string() {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
const MRegExpExec *mir() const {
|
||||
return mir_->toRegExpExec();
|
||||
}
|
||||
};
|
||||
|
||||
class LRegExpTest : public LCallInstructionHelper<1, 2, 0>
|
||||
{
|
||||
public:
|
||||
|
@ -149,6 +149,7 @@
|
||||
_(OsrReturnValue) \
|
||||
_(OsrArgumentsObject) \
|
||||
_(RegExp) \
|
||||
_(RegExpExec) \
|
||||
_(RegExpTest) \
|
||||
_(Lambda) \
|
||||
_(LambdaForSingleton) \
|
||||
|
@ -1945,6 +1945,17 @@ LIRGenerator::visitRegExp(MRegExp *ins)
|
||||
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitRegExpExec(MRegExpExec *ins)
|
||||
{
|
||||
JS_ASSERT(ins->regexp()->type() == MIRType_Object);
|
||||
JS_ASSERT(ins->string()->type() == MIRType_String);
|
||||
|
||||
LRegExpExec *lir = new(alloc()) LRegExpExec(useRegisterAtStart(ins->regexp()),
|
||||
useRegisterAtStart(ins->string()));
|
||||
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitRegExpTest(MRegExpTest *ins)
|
||||
{
|
||||
|
@ -162,6 +162,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
bool visitTruncateToInt32(MTruncateToInt32 *truncate);
|
||||
bool visitToString(MToString *convert);
|
||||
bool visitRegExp(MRegExp *ins);
|
||||
bool visitRegExpExec(MRegExpExec *ins);
|
||||
bool visitRegExpTest(MRegExpTest *ins);
|
||||
bool visitLambda(MLambda *ins);
|
||||
bool visitLambdaPar(MLambdaPar *ins);
|
||||
|
@ -119,6 +119,8 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
|
||||
return inlineStrCharAt(callInfo);
|
||||
|
||||
// RegExp natives.
|
||||
if (native == regexp_exec && CallResultEscapes(pc))
|
||||
return inlineRegExpExec(callInfo);
|
||||
if (native == regexp_exec && !CallResultEscapes(pc))
|
||||
return inlineRegExpTest(callInfo);
|
||||
if (native == regexp_test)
|
||||
@ -1066,6 +1068,34 @@ IonBuilder::inlineStrCharAt(CallInfo &callInfo)
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineRegExpExec(CallInfo &callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (callInfo.thisArg()->type() != MIRType_Object)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::TemporaryTypeSet *thisTypes = callInfo.thisArg()->resultTypeSet();
|
||||
const Class *clasp = thisTypes ? thisTypes->getKnownClass() : nullptr;
|
||||
if (clasp != &RegExpObject::class_)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (callInfo.getArg(0)->type() != MIRType_String)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
callInfo.unwrapArgs();
|
||||
|
||||
MInstruction *exec = MRegExpExec::New(alloc(), callInfo.thisArg(), callInfo.getArg(0));
|
||||
current->add(exec);
|
||||
current->push(exec);
|
||||
if (!resumeAfter(exec))
|
||||
return InliningStatus_Error;
|
||||
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineRegExpTest(CallInfo &callInfo)
|
||||
{
|
||||
|
@ -4892,6 +4892,43 @@ class MRegExp : public MNullaryInstruction
|
||||
}
|
||||
};
|
||||
|
||||
class MRegExpExec
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<1>, StringPolicy<0> >
|
||||
{
|
||||
private:
|
||||
|
||||
MRegExpExec(MDefinition *regexp, MDefinition *string)
|
||||
: MBinaryInstruction(string, regexp)
|
||||
{
|
||||
// May be object or null.
|
||||
setResultType(MIRType_Value);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(RegExpExec)
|
||||
|
||||
static MRegExpExec *New(TempAllocator &alloc, MDefinition *regexp, MDefinition *string) {
|
||||
return new(alloc) MRegExpExec(regexp, string);
|
||||
}
|
||||
|
||||
MDefinition *string() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
MDefinition *regexp() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
bool possiblyCalls() const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class MRegExpTest
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<ObjectPolicy<1>, StringPolicy<0> >
|
||||
|
@ -100,6 +100,7 @@ namespace jit {
|
||||
_(OsrEntry) \
|
||||
_(Nop) \
|
||||
_(RegExp) \
|
||||
_(RegExpExec) \
|
||||
_(RegExpTest) \
|
||||
_(Lambda) \
|
||||
_(ImplicitThis) \
|
||||
|
@ -281,6 +281,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
||||
UNSAFE_OP(Pow)
|
||||
UNSAFE_OP(PowHalf)
|
||||
UNSAFE_OP(RegExpTest)
|
||||
UNSAFE_OP(RegExpExec)
|
||||
UNSAFE_OP(CallInstanceOf)
|
||||
UNSAFE_OP(FunctionBoundary)
|
||||
UNSAFE_OP(GuardString)
|
||||
|
Loading…
Reference in New Issue
Block a user