зеркало из https://github.com/mozilla/gecko-dev.git
Bug 935016 - Specialize string.split(string) in IonMonkey. r=bhackett
This commit is contained in:
Родитель
9f29749647
Коммит
7cb4f81d82
|
@ -7451,6 +7451,18 @@ GetTemplateObjectForNative(JSContext *cx, HandleScript script, jsbytecode *pc,
|
|||
}
|
||||
}
|
||||
|
||||
if (native == js::str_split && args.length() == 1 && args[0].isString()) {
|
||||
res.set(NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject));
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
types::TypeObject *type = types::TypeScript::InitObject(cx, script, pc, JSProto_Array);
|
||||
if (!type)
|
||||
return false;
|
||||
res->setType(type);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (native == js_String) {
|
||||
RootedString emptyString(cx, cx->runtime()->emptyString);
|
||||
res.set(StringObject::create(cx, emptyString, TenuredObject));
|
||||
|
|
|
@ -4625,6 +4625,19 @@ CodeGenerator::visitFromCharCode(LFromCharCode *lir)
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*StringSplitFn)(JSContext *, HandleTypeObject, HandleString, HandleString);
|
||||
static const VMFunction StringSplitInfo = FunctionInfo<StringSplitFn>(js::str_split_string);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitStringSplit(LStringSplit *lir)
|
||||
{
|
||||
pushArg(ToRegister(lir->separator()));
|
||||
pushArg(ToRegister(lir->string()));
|
||||
pushArg(ImmGCPtr(lir->mir()->typeObject()));
|
||||
|
||||
return callVM(StringSplitInfo, lir);
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitInitializedLength(LInitializedLength *lir)
|
||||
{
|
||||
|
|
|
@ -201,6 +201,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool visitConcatPar(LConcatPar *lir);
|
||||
bool visitCharCodeAt(LCharCodeAt *lir);
|
||||
bool visitFromCharCode(LFromCharCode *lir);
|
||||
bool visitStringSplit(LStringSplit *lir);
|
||||
bool visitFunctionEnvironment(LFunctionEnvironment *lir);
|
||||
bool visitForkJoinSlice(LForkJoinSlice *lir);
|
||||
bool visitGuardThreadLocalObject(LGuardThreadLocalObject *lir);
|
||||
|
|
|
@ -559,6 +559,7 @@ class IonBuilder : public MIRGenerator
|
|||
|
||||
// String natives.
|
||||
InliningStatus inlineStringObject(CallInfo &callInfo);
|
||||
InliningStatus inlineStringSplit(CallInfo &callInfo);
|
||||
InliningStatus inlineStrCharCodeAt(CallInfo &callInfo);
|
||||
InliningStatus inlineStrFromCharCode(CallInfo &callInfo);
|
||||
InliningStatus inlineStrCharAt(CallInfo &callInfo);
|
||||
|
|
|
@ -2720,6 +2720,26 @@ class LFromCharCode : public LInstructionHelper<1, 1, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LStringSplit : public LCallInstructionHelper<1, 2, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(StringSplit)
|
||||
|
||||
LStringSplit(const LAllocation &string, const LAllocation &separator) {
|
||||
setOperand(0, string);
|
||||
setOperand(1, separator);
|
||||
}
|
||||
const LAllocation *string() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LAllocation *separator() {
|
||||
return getOperand(1);
|
||||
}
|
||||
const MStringSplit *mir() const {
|
||||
return mir_->toStringSplit();
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a 32-bit integer to a double.
|
||||
class LInt32ToDouble : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
|
|
|
@ -126,6 +126,7 @@
|
|||
_(ConcatPar) \
|
||||
_(CharCodeAt) \
|
||||
_(FromCharCode) \
|
||||
_(StringSplit) \
|
||||
_(Int32ToDouble) \
|
||||
_(Float32ToDouble) \
|
||||
_(DoubleToFloat32) \
|
||||
|
|
|
@ -2524,6 +2524,18 @@ LIRGenerator::visitArrayConcat(MArrayConcat *ins)
|
|||
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitStringSplit(MStringSplit *ins)
|
||||
{
|
||||
JS_ASSERT(ins->type() == MIRType_Object);
|
||||
JS_ASSERT(ins->string()->type() == MIRType_String);
|
||||
JS_ASSERT(ins->separator()->type() == MIRType_String);
|
||||
|
||||
LStringSplit *lir = new LStringSplit(useRegisterAtStart(ins->string()),
|
||||
useRegisterAtStart(ins->separator()));
|
||||
return defineReturn(lir, ins) && assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitLoadTypedArrayElement(MLoadTypedArrayElement *ins)
|
||||
{
|
||||
|
|
|
@ -148,6 +148,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
bool visitConcatPar(MConcatPar *ins);
|
||||
bool visitCharCodeAt(MCharCodeAt *ins);
|
||||
bool visitFromCharCode(MFromCharCode *ins);
|
||||
bool visitStringSplit(MStringSplit *ins);
|
||||
bool visitStart(MStart *start);
|
||||
bool visitOsrEntry(MOsrEntry *entry);
|
||||
bool visitNop(MNop *nop);
|
||||
|
|
|
@ -105,6 +105,8 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
|
|||
// String natives.
|
||||
if (native == js_String)
|
||||
return inlineStringObject(callInfo);
|
||||
if (native == js::str_split)
|
||||
return inlineStringSplit(callInfo);
|
||||
if (native == js_str_charCodeAt)
|
||||
return inlineStrCharCodeAt(callInfo);
|
||||
if (native == js::str_fromCharCode)
|
||||
|
@ -910,6 +912,43 @@ IonBuilder::inlineStringObject(CallInfo &callInfo)
|
|||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineStringSplit(CallInfo &callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.thisArg()->type() != MIRType_String)
|
||||
return InliningStatus_NotInlined;
|
||||
if (callInfo.getArg(0)->type() != MIRType_String)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
JSObject *templateObject = inspector->getTemplateObjectForNative(pc, js::str_split);
|
||||
if (!templateObject)
|
||||
return InliningStatus_NotInlined;
|
||||
JS_ASSERT(templateObject->is<ArrayObject>());
|
||||
|
||||
types::TypeObjectKey *retType = types::TypeObjectKey::get(templateObject);
|
||||
if (retType->unknownProperties())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
types::HeapTypeSetKey key = retType->property(JSID_VOID);
|
||||
if (!key.maybeTypes())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (!key.maybeTypes()->hasType(types::Type::StringType())) {
|
||||
key.freeze(constraints());
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
callInfo.unwrapArgs();
|
||||
|
||||
MStringSplit *ins = MStringSplit::New(callInfo.thisArg(), callInfo.getArg(0), templateObject);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineStrCharCodeAt(CallInfo &callInfo)
|
||||
{
|
||||
|
|
|
@ -4152,6 +4152,48 @@ class MFromCharCode
|
|||
}
|
||||
};
|
||||
|
||||
class MStringSplit
|
||||
: public MBinaryInstruction,
|
||||
public MixPolicy<StringPolicy<0>, StringPolicy<1> >
|
||||
{
|
||||
types::TypeObject *typeObject_;
|
||||
|
||||
MStringSplit(MDefinition *string, MDefinition *sep, JSObject *templateObject)
|
||||
: MBinaryInstruction(string, sep),
|
||||
typeObject_(templateObject->type())
|
||||
{
|
||||
setResultType(MIRType_Object);
|
||||
setResultTypeSet(MakeSingletonTypeSet(templateObject));
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(StringSplit)
|
||||
|
||||
static MStringSplit *New(MDefinition *string, MDefinition *sep, JSObject *templateObject) {
|
||||
return new MStringSplit(string, sep, templateObject);
|
||||
}
|
||||
types::TypeObject *typeObject() const {
|
||||
return typeObject_;
|
||||
}
|
||||
MDefinition *string() const {
|
||||
return getOperand(0);
|
||||
}
|
||||
MDefinition *separator() const {
|
||||
return getOperand(1);
|
||||
}
|
||||
TypePolicy *typePolicy() {
|
||||
return this;
|
||||
}
|
||||
bool possiblyCalls() const {
|
||||
return true;
|
||||
}
|
||||
virtual AliasSet getAliasSet() const {
|
||||
// Although this instruction returns a new array, we don't have to mark
|
||||
// it as store instruction, see also MNewArray.
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
// Returns an object to use as |this| value. See also ComputeThis and
|
||||
// BoxNonStrictThis in Interpreter.h.
|
||||
class MComputeThis
|
||||
|
|
|
@ -72,6 +72,7 @@ namespace jit {
|
|||
_(ConcatPar) \
|
||||
_(CharCodeAt) \
|
||||
_(FromCharCode) \
|
||||
_(StringSplit) \
|
||||
_(Return) \
|
||||
_(Throw) \
|
||||
_(Box) \
|
||||
|
|
|
@ -163,6 +163,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
|||
SAFE_OP(ConcatPar)
|
||||
UNSAFE_OP(CharCodeAt)
|
||||
UNSAFE_OP(FromCharCode)
|
||||
UNSAFE_OP(StringSplit)
|
||||
SAFE_OP(Return)
|
||||
CUSTOM_OP(Throw)
|
||||
SAFE_OP(Box) // Boxing just creates a JSVal, doesn't alloc.
|
||||
|
|
|
@ -3005,7 +3005,7 @@ class SplitMatchResult {
|
|||
} /* anonymous namespace */
|
||||
|
||||
template<class Matcher>
|
||||
static JSObject *
|
||||
static ArrayObject *
|
||||
SplitHelper(JSContext *cx, Handle<JSLinearString*> str, uint32_t limit, const Matcher &splitMatch,
|
||||
Handle<TypeObject*> type)
|
||||
{
|
||||
|
@ -3289,6 +3289,28 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::str_split_string(JSContext *cx, HandleTypeObject type, HandleString str, HandleString sep)
|
||||
{
|
||||
Rooted<JSLinearString*> linearStr(cx, str->ensureLinear(cx));
|
||||
if (!linearStr)
|
||||
return nullptr;
|
||||
|
||||
Rooted<JSLinearString*> linearSep(cx, sep->ensureLinear(cx));
|
||||
if (!linearSep)
|
||||
return nullptr;
|
||||
|
||||
uint32_t limit = UINT32_MAX;
|
||||
|
||||
SplitStringMatcher matcher(cx, linearSep);
|
||||
ArrayObject *aobj = SplitHelper(cx, linearStr, limit, matcher, type);
|
||||
if (!aobj)
|
||||
return nullptr;
|
||||
|
||||
aobj->setType(type);
|
||||
return aobj;
|
||||
}
|
||||
|
||||
static bool
|
||||
str_substr(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "jsutil.h"
|
||||
#include "NamespaceImports.h"
|
||||
|
||||
#include "gc/Rooting.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "vm/Unicode.h"
|
||||
|
||||
|
@ -355,6 +356,9 @@ str_search(JSContext *cx, unsigned argc, Value *vp);
|
|||
bool
|
||||
str_split(JSContext *cx, unsigned argc, Value *vp);
|
||||
|
||||
JSObject *
|
||||
str_split_string(JSContext *cx, HandleTypeObject type, HandleString str, HandleString sep);
|
||||
|
||||
bool
|
||||
str_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
|
||||
MutableHandleObject objp);
|
||||
|
|
Загрузка…
Ссылка в новой задаче