From 7c9aab27bcfab7da70620539dc63fa3f378a0de8 Mon Sep 17 00:00:00 2001 From: Tom Schuster Date: Mon, 3 Apr 2017 22:24:03 +0200 Subject: [PATCH] Bug 1352006 - Inline NewArrayIterator in Ion. r=jandem --- js/src/jit/BaselineIC.cpp | 5 +++++ js/src/jit/CodeGenerator.cpp | 20 +++++++++++++++++++ js/src/jit/CodeGenerator.h | 1 + js/src/jit/InlinableNatives.h | 2 ++ js/src/jit/IonBuilder.h | 3 +++ js/src/jit/Lowering.cpp | 8 ++++++++ js/src/jit/Lowering.h | 1 + js/src/jit/MCallOptimize.cpp | 30 +++++++++++++++++++++++++++++ js/src/jit/MIR.h | 27 ++++++++++++++++++++++++++ js/src/jit/MOpcodes.h | 1 + js/src/jit/VMFunctions.h | 1 + js/src/jit/shared/LIR-shared.h | 18 +++++++++++++++++ js/src/jit/shared/LOpcodes-shared.h | 1 + js/src/jsiter.cpp | 11 +++++++++++ js/src/jsiter.h | 3 +++ js/src/vm/SelfHosting.cpp | 15 +++++++-------- js/src/vm/SelfHosting.h | 3 +++ 17 files changed, 142 insertions(+), 8 deletions(-) diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index de9f47107c24..e6962472568c 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -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; diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index db658d1d1508..1222638ea976 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -5635,6 +5635,26 @@ CodeGenerator::visitNewArrayDynamicLength(LNewArrayDynamicLength* lir) masm.bind(ool->rejoin()); } +typedef ArrayIteratorObject* (*NewArrayIteratorObjectFn)(JSContext*, NewObjectKind); +static const VMFunction NewArrayIteratorObjectInfo = + FunctionInfo(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(TypedArrayCreateWithTemplate, diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h index f0f6fc0ab610..5c3cadd45586 100644 --- a/js/src/jit/CodeGenerator.h +++ b/js/src/jit/CodeGenerator.h @@ -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); diff --git a/js/src/jit/InlinableNatives.h b/js/src/jit/InlinableNatives.h index 082bd6d009ec..200347327eee 100644 --- a/js/src/jit/InlinableNatives.h +++ b/js/src/jit/InlinableNatives.h @@ -129,6 +129,8 @@ \ _(IntrinsicGetNextSetEntryForIterator) \ \ + _(IntrinsicNewArrayIterator) \ + \ _(IntrinsicArrayBufferByteLength) \ _(IntrinsicPossiblyWrappedArrayBufferByteLength) \ \ diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index 1ed3bdce9230..ac6c55a29452 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -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); diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index 686d0ef537a3..0bdac9979d80 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -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) { diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h index c5cd456069ac..dc27c764558f 100644 --- a/js/src/jit/Lowering.h +++ b/js/src/jit/Lowering.h @@ -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); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index eafd0e866155..ca4bc8a06581 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -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()); + + 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) { diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 81f98bb12216..3849276a1791 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -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 templateObject_; diff --git a/js/src/jit/MOpcodes.h b/js/src/jit/MOpcodes.h index df2bddefd13a..f64293b0fda0 100644 --- a/js/src/jit/MOpcodes.h +++ b/js/src/jit/MOpcodes.h @@ -133,6 +133,7 @@ namespace jit { _(NewArray) \ _(NewArrayCopyOnWrite) \ _(NewArrayDynamicLength) \ + _(NewArrayIterator) \ _(NewTypedArray) \ _(NewTypedArrayDynamicLength) \ _(NewObject) \ diff --git a/js/src/jit/VMFunctions.h b/js/src/jit/VMFunctions.h index c50683fc3561..30054310f3d7 100644 --- a/js/src/jit/VMFunctions.h +++ b/js/src/jit/VMFunctions.h @@ -282,6 +282,7 @@ template <> struct TypeToDataType { static const DataType re template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; +template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Object; }; template <> struct TypeToDataType { static const DataType result = Type_Handle; }; diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h index 62e54ea1fed6..efab506281e8 100644 --- a/js/src/jit/shared/LIR-shared.h +++ b/js/src/jit/shared/LIR-shared.h @@ -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: diff --git a/js/src/jit/shared/LOpcodes-shared.h b/js/src/jit/shared/LOpcodes-shared.h index c270335f34cc..74f340df3992 100644 --- a/js/src/jit/shared/LOpcodes-shared.h +++ b/js/src/jit/shared/LOpcodes-shared.h @@ -67,6 +67,7 @@ _(NewArray) \ _(NewArrayCopyOnWrite) \ _(NewArrayDynamicLength) \ + _(NewArrayIterator) \ _(NewTypedArray) \ _(NewTypedArrayDynamicLength) \ _(NewObject) \ diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index b958bd992fb0..03c0b2555ecb 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -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(cx, proto, newKind); +} + static const JSFunctionSpec array_iterator_methods[] = { JS_SELF_HOSTED_FN("next", "ArrayIteratorNext", 0, 0), JS_FS_END diff --git a/js/src/jsiter.h b/js/src/jsiter.h index ada903dbb6d7..cf2c9c710804 100644 --- a/js/src/jsiter.h +++ b/js/src/jsiter.h @@ -145,6 +145,9 @@ class ArrayIteratorObject : public JSObject static const Class class_; }; +ArrayIteratorObject* +NewArrayIteratorObject(JSContext* cx, NewObjectKind newKind = GenericObject); + class StringIteratorObject : public JSObject { public: diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 0d05e5784190..5c54e25b062b 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -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>, 2,0), diff --git a/js/src/vm/SelfHosting.h b/js/src/vm/SelfHosting.h index f4f2a44473da..321297aca65d 100644 --- a/js/src/vm/SelfHosting.h +++ b/js/src/vm/SelfHosting.h @@ -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_ */