зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1352006 - Inline NewArrayIterator in Ion. r=jandem
This commit is contained in:
Родитель
e0317a08e6
Коммит
7c9aab27bc
|
@ -1914,6 +1914,11 @@ GetTemplateObjectForNative(JSContext* cx, HandleFunction target, const CallArgs&
|
|||
return !!res;
|
||||
}
|
||||
|
||||
if (native == js::intrinsic_NewArrayIterator) {
|
||||
res.set(NewArrayIteratorObject(cx, TenuredObject));
|
||||
return !!res;
|
||||
}
|
||||
|
||||
if (JitSupportsSimd() && GetTemplateObjectForSimd(cx, target, res))
|
||||
return !!res;
|
||||
|
||||
|
|
|
@ -5635,6 +5635,26 @@ CodeGenerator::visitNewArrayDynamicLength(LNewArrayDynamicLength* lir)
|
|||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
typedef ArrayIteratorObject* (*NewArrayIteratorObjectFn)(JSContext*, NewObjectKind);
|
||||
static const VMFunction NewArrayIteratorObjectInfo =
|
||||
FunctionInfo<NewArrayIteratorObjectFn>(NewArrayIteratorObject, "NewArrayIteratorObject");
|
||||
|
||||
void
|
||||
CodeGenerator::visitNewArrayIterator(LNewArrayIterator* lir)
|
||||
{
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
JSObject* templateObject = lir->mir()->templateObject();
|
||||
|
||||
OutOfLineCode* ool = oolCallVM(NewArrayIteratorObjectInfo, lir,
|
||||
ArgList(Imm32(GenericObject)),
|
||||
StoreRegisterTo(objReg));
|
||||
|
||||
masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap, ool->entry());
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
typedef TypedArrayObject* (*TypedArrayConstructorOneArgFn)(JSContext*, HandleObject, int32_t length);
|
||||
static const VMFunction TypedArrayConstructorOneArgInfo =
|
||||
FunctionInfo<TypedArrayConstructorOneArgFn>(TypedArrayCreateWithTemplate,
|
||||
|
|
|
@ -198,6 +198,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||
void visitOutOfLineNewArray(OutOfLineNewArray* ool);
|
||||
void visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite* lir);
|
||||
void visitNewArrayDynamicLength(LNewArrayDynamicLength* lir);
|
||||
void visitNewArrayIterator(LNewArrayIterator* lir);
|
||||
void visitNewTypedArray(LNewTypedArray* lir);
|
||||
void visitNewTypedArrayDynamicLength(LNewTypedArrayDynamicLength* lir);
|
||||
void visitNewObjectVMCall(LNewObject* lir);
|
||||
|
|
|
@ -129,6 +129,8 @@
|
|||
\
|
||||
_(IntrinsicGetNextSetEntryForIterator) \
|
||||
\
|
||||
_(IntrinsicNewArrayIterator) \
|
||||
\
|
||||
_(IntrinsicArrayBufferByteLength) \
|
||||
_(IntrinsicPossiblyWrappedArrayBufferByteLength) \
|
||||
\
|
||||
|
|
|
@ -631,6 +631,9 @@ class IonBuilder
|
|||
InliningResult inlineArraySlice(CallInfo& callInfo);
|
||||
InliningResult inlineArrayJoin(CallInfo& callInfo);
|
||||
|
||||
// Array intrinsics.
|
||||
InliningResult inlineNewArrayIterator(CallInfo& callInfo);
|
||||
|
||||
// Math natives.
|
||||
InliningResult inlineMathAbs(CallInfo& callInfo);
|
||||
InliningResult inlineMathFloor(CallInfo& callInfo);
|
||||
|
|
|
@ -243,6 +243,14 @@ LIRGenerator::visitNewArrayDynamicLength(MNewArrayDynamicLength* ins)
|
|||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitNewArrayIterator(MNewArrayIterator* ins)
|
||||
{
|
||||
LNewArrayIterator* lir = new(alloc()) LNewArrayIterator(temp());
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitNewTypedArray(MNewTypedArray* ins)
|
||||
{
|
||||
|
|
|
@ -78,6 +78,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
void visitNewArray(MNewArray* ins);
|
||||
void visitNewArrayCopyOnWrite(MNewArrayCopyOnWrite* ins);
|
||||
void visitNewArrayDynamicLength(MNewArrayDynamicLength* ins);
|
||||
void visitNewArrayIterator(MNewArrayIterator* ins);
|
||||
void visitNewTypedArray(MNewTypedArray* ins);
|
||||
void visitNewTypedArrayDynamicLength(MNewTypedArrayDynamicLength* ins);
|
||||
void visitNewObject(MNewObject* ins);
|
||||
|
|
|
@ -88,6 +88,10 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
|||
case InlinableNative::ArraySlice:
|
||||
return inlineArraySlice(callInfo);
|
||||
|
||||
// Array intrinsics.
|
||||
case InlinableNative::IntrinsicNewArrayIterator:
|
||||
return inlineNewArrayIterator(callInfo);
|
||||
|
||||
// Atomic natives.
|
||||
case InlinableNative::AtomicsCompareExchange:
|
||||
return inlineAtomicsCompareExchange(callInfo);
|
||||
|
@ -886,6 +890,32 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
|||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningResult
|
||||
IonBuilder::inlineNewArrayIterator(CallInfo& callInfo)
|
||||
{
|
||||
if (callInfo.argc() != 0 || callInfo.constructing()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::CantInlineNativeBadForm);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
JSObject* templateObject = inspector->getTemplateObjectForNative(pc, js::intrinsic_NewArrayIterator);
|
||||
if (!templateObject)
|
||||
return InliningStatus_NotInlined;
|
||||
MOZ_ASSERT(templateObject->is<ArrayIteratorObject>());
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
MConstant* templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
|
||||
current->add(templateConst);
|
||||
|
||||
MNewArrayIterator* ins = MNewArrayIterator::New(alloc(), constraints(), templateConst);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
|
||||
MOZ_TRY(resumeAfter(ins));
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningResult
|
||||
IonBuilder::inlineMathAbs(CallInfo& callInfo)
|
||||
{
|
||||
|
|
|
@ -3532,6 +3532,33 @@ class MNewObject
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class MNewArrayIterator
|
||||
: public MUnaryInstruction,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
explicit MNewArrayIterator(CompilerConstraintList* constraints, MConstant* templateConst)
|
||||
: MUnaryInstruction(templateConst)
|
||||
{
|
||||
setResultType(MIRType::Object);
|
||||
setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject()));
|
||||
templateConst->setEmittedAtUses();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(NewArrayIterator)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
JSObject* templateObject() {
|
||||
return getOperand(0)->toConstant()->toObjectOrNull();
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class MNewTypedObject : public MNullaryInstruction
|
||||
{
|
||||
CompilerGCPointer<InlineTypedObject*> templateObject_;
|
||||
|
|
|
@ -133,6 +133,7 @@ namespace jit {
|
|||
_(NewArray) \
|
||||
_(NewArrayCopyOnWrite) \
|
||||
_(NewArrayDynamicLength) \
|
||||
_(NewArrayIterator) \
|
||||
_(NewTypedArray) \
|
||||
_(NewTypedArrayDynamicLength) \
|
||||
_(NewObject) \
|
||||
|
|
|
@ -282,6 +282,7 @@ template <> struct TypeToDataType<NamedLambdaObject*> { static const DataType re
|
|||
template <> struct TypeToDataType<LexicalEnvironmentObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<ArrayObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<TypedArrayObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<ArrayIteratorObject*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<JSString*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<JSFlatString*> { static const DataType result = Type_Object; };
|
||||
template <> struct TypeToDataType<HandleObject> { static const DataType result = Type_Handle; };
|
||||
|
|
|
@ -1062,6 +1062,24 @@ class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1>
|
|||
}
|
||||
};
|
||||
|
||||
class LNewArrayIterator : public LInstructionHelper<1, 0, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(NewArrayIterator)
|
||||
|
||||
explicit LNewArrayIterator(const LDefinition& temp) {
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LDefinition* temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
MNewArrayIterator* mir() const {
|
||||
return mir_->toNewArrayIterator();
|
||||
}
|
||||
};
|
||||
|
||||
class LNewTypedArray : public LInstructionHelper<1, 0, 2>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
_(NewArray) \
|
||||
_(NewArrayCopyOnWrite) \
|
||||
_(NewArrayDynamicLength) \
|
||||
_(NewArrayIterator) \
|
||||
_(NewTypedArray) \
|
||||
_(NewTypedArrayDynamicLength) \
|
||||
_(NewObject) \
|
||||
|
|
|
@ -1134,6 +1134,17 @@ const Class ArrayIteratorObject::class_ = {
|
|||
JSCLASS_HAS_RESERVED_SLOTS(ArrayIteratorSlotCount)
|
||||
};
|
||||
|
||||
|
||||
ArrayIteratorObject*
|
||||
js::NewArrayIteratorObject(JSContext* cx, NewObjectKind newKind)
|
||||
{
|
||||
RootedObject proto(cx, GlobalObject::getOrCreateArrayIteratorPrototype(cx, cx->global()));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
|
||||
return NewObjectWithGivenProto<ArrayIteratorObject>(cx, proto, newKind);
|
||||
}
|
||||
|
||||
static const JSFunctionSpec array_iterator_methods[] = {
|
||||
JS_SELF_HOSTED_FN("next", "ArrayIteratorNext", 0, 0),
|
||||
JS_FS_END
|
||||
|
|
|
@ -145,6 +145,9 @@ class ArrayIteratorObject : public JSObject
|
|||
static const Class class_;
|
||||
};
|
||||
|
||||
ArrayIteratorObject*
|
||||
NewArrayIteratorObject(JSContext* cx, NewObjectKind newKind = GenericObject);
|
||||
|
||||
class StringIteratorObject : public JSObject
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "jsfriendapi.h"
|
||||
#include "jsfun.h"
|
||||
#include "jshashutil.h"
|
||||
#include "jsiter.h"
|
||||
#include "jsstr.h"
|
||||
#include "jsweakmap.h"
|
||||
#include "jswrapper.h"
|
||||
|
@ -754,17 +755,13 @@ intrinsic_GetIteratorPrototype(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, Value* vp)
|
||||
bool
|
||||
js::intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() == 0);
|
||||
|
||||
RootedObject proto(cx, GlobalObject::getOrCreateArrayIteratorPrototype(cx, cx->global()));
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
JSObject* obj = NewObjectWithGivenProto(cx, &ArrayIteratorObject::class_, proto);
|
||||
JSObject* obj = NewArrayIteratorObject(cx);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
@ -2441,7 +2438,9 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
|
||||
JS_FN("GetIteratorPrototype", intrinsic_GetIteratorPrototype, 0,0),
|
||||
|
||||
JS_FN("NewArrayIterator", intrinsic_NewArrayIterator, 0,0),
|
||||
JS_INLINABLE_FN("NewArrayIterator", intrinsic_NewArrayIterator, 0,0,
|
||||
IntrinsicNewArrayIterator),
|
||||
|
||||
JS_FN("CallArrayIteratorMethodIfWrapped",
|
||||
CallNonGenericSelfhostedMethod<Is<ArrayIteratorObject>>, 2,0),
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ CallSelfHostedFunction(JSContext* cx, HandlePropertyName name, HandleValue thisv
|
|||
bool
|
||||
intrinsic_StringSplitString(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool
|
||||
intrinsic_NewArrayIterator(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* vm_SelfHosting_h_ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче