From 863f2c7e9c0825ccd3158f7312d29f956dbf4b7b Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Sat, 5 Mar 2016 18:56:36 +0900 Subject: [PATCH] Bug 1165053 - Part 0.2: Inline PossiblyWrappedArrayBufferByteLength self-hosting intrinsic. r=jwalden --- ...estPossiblyWrappedArrayBufferByteLength.js | 41 +++++++++++++++++++ js/src/jit/InlinableNatives.h | 2 + js/src/jit/IonBuilder.cpp | 9 ++++ js/src/jit/IonBuilder.h | 5 +++ js/src/jit/MCallOptimize.cpp | 38 +++++++++++++++++ js/src/vm/SelfHosting.cpp | 3 +- 6 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 js/src/jit-test/tests/ion/testPossiblyWrappedArrayBufferByteLength.js diff --git a/js/src/jit-test/tests/ion/testPossiblyWrappedArrayBufferByteLength.js b/js/src/jit-test/tests/ion/testPossiblyWrappedArrayBufferByteLength.js new file mode 100644 index 000000000000..ef41f89c8ba2 --- /dev/null +++ b/js/src/jit-test/tests/ion/testPossiblyWrappedArrayBufferByteLength.js @@ -0,0 +1,41 @@ +var PossiblyWrappedArrayBufferByteLength = getSelfHostedValue("PossiblyWrappedArrayBufferByteLength"); + +setJitCompilerOption("ion.warmup.trigger", 50); + +function testBasic() { + var arr = [1, 2, 3]; + var tarr = new Int32Array(arr); + var abuf = tarr.buffer; + + var arrLength = arr.length; + var bytesPerElement = Int32Array.BYTES_PER_ELEMENT; + + var f = function() { + assertEq(PossiblyWrappedArrayBufferByteLength(abuf), arrLength * bytesPerElement); + }; + do { + f(); + } while (!inIon()); +} +testBasic(); + +function testWrapped() { + var g = newGlobal(); +g.eval(` +var arr = [1, 2, 3]; +var tarr = new Int32Array(arr); +var abuf = tarr.buffer; +`); + + var abuf = g.abuf; + var arrLength = g.arr.length; + var bytesPerElement = g.Int32Array.BYTES_PER_ELEMENT; + + var f = function() { + assertEq(PossiblyWrappedArrayBufferByteLength(abuf), arrLength * bytesPerElement); + }; + do { + f(); + } while (!inIon()); +} +testWrapped(); diff --git a/js/src/jit/InlinableNatives.h b/js/src/jit/InlinableNatives.h index 3364bd512bf6..00fc4df06243 100644 --- a/js/src/jit/InlinableNatives.h +++ b/js/src/jit/InlinableNatives.h @@ -111,6 +111,8 @@ \ _(IntrinsicGetNextMapEntryForIterator) \ \ + _(IntrinsicPossiblyWrappedArrayBufferByteLength) \ + \ _(IntrinsicIsTypedArray) \ _(IntrinsicIsPossiblyWrappedTypedArray) \ _(IntrinsicTypedArrayLength) \ diff --git a/js/src/jit/IonBuilder.cpp b/js/src/jit/IonBuilder.cpp index ad59f99667d8..960171a1496c 100644 --- a/js/src/jit/IonBuilder.cpp +++ b/js/src/jit/IonBuilder.cpp @@ -9500,6 +9500,15 @@ IonBuilder::jsop_getelem_dense(MDefinition* obj, MDefinition* index, JSValueType return pushTypeBarrier(load, types, barrier); } +MInstruction* +IonBuilder::addArrayBufferByteLength(MDefinition* obj) +{ + MLoadFixedSlot* ins = MLoadFixedSlot::New(alloc(), obj, ArrayBufferObject::BYTE_LENGTH_SLOT); + current->add(ins); + ins->setResultType(MIRType_Int32); + return ins; +} + void IonBuilder::addTypedArrayLengthAndData(MDefinition* obj, BoundsChecking checking, diff --git a/js/src/jit/IonBuilder.h b/js/src/jit/IonBuilder.h index 2f09796ffd05..0f949b27f9c8 100644 --- a/js/src/jit/IonBuilder.h +++ b/js/src/jit/IonBuilder.h @@ -623,6 +623,8 @@ class IonBuilder enum BoundsChecking { DoBoundsCheck, SkipBoundsCheck }; + MInstruction* addArrayBufferByteLength(MDefinition* obj); + // Add instructions to compute a typed array's length and data. Also // optionally convert |*index| into a bounds-checked definition, if // requested. @@ -844,6 +846,9 @@ class IonBuilder // Map intrinsics. InliningStatus inlineGetNextMapEntryForIterator(CallInfo& callInfo); + // ArrayBuffer intrinsics. + InliningStatus inlinePossiblyWrappedArrayBufferByteLength(CallInfo& callInfo); + // TypedArray intrinsics. enum WrappingBehavior { AllowWrappedTypedArrays, RejectWrappedTypedArrays }; InliningStatus inlineIsTypedArrayHelper(CallInfo& callInfo, WrappingBehavior wrappingBehavior); diff --git a/js/src/jit/MCallOptimize.cpp b/js/src/jit/MCallOptimize.cpp index a5c736fdf3c8..c7cdd8284779 100644 --- a/js/src/jit/MCallOptimize.cpp +++ b/js/src/jit/MCallOptimize.cpp @@ -264,6 +264,10 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target) case InlinableNative::IntrinsicGetNextMapEntryForIterator: return inlineGetNextMapEntryForIterator(callInfo); + // ArrayBuffer intrinsics. + case InlinableNative::IntrinsicPossiblyWrappedArrayBufferByteLength: + return inlinePossiblyWrappedArrayBufferByteLength(callInfo); + // TypedArray intrinsics. case InlinableNative::IntrinsicIsTypedArray: return inlineIsTypedArray(callInfo); @@ -2234,6 +2238,40 @@ IonBuilder::inlineGetNextMapEntryForIterator(CallInfo& callInfo) return InliningStatus_Inlined; } +static bool +IsArrayBufferObject(CompilerConstraintList* constraints, MDefinition* def) +{ + MOZ_ASSERT(def->type() == MIRType_Object); + + TemporaryTypeSet* types = def->resultTypeSet(); + if (!types) + return false; + + return types->getKnownClass(constraints) == &ArrayBufferObject::class_; +} + +IonBuilder::InliningStatus +IonBuilder::inlinePossiblyWrappedArrayBufferByteLength(CallInfo& callInfo) +{ + MOZ_ASSERT(!callInfo.constructing()); + MOZ_ASSERT(callInfo.argc() == 1); + + MDefinition* objArg = callInfo.getArg(0); + if (objArg->type() != MIRType_Object) + return InliningStatus_NotInlined; + if (getInlineReturnType() != MIRType_Int32) + return InliningStatus_NotInlined; + + if (!IsArrayBufferObject(constraints(), objArg)) + return InliningStatus_NotInlined; + + MInstruction* ins = addArrayBufferByteLength(objArg); + current->push(ins); + + callInfo.setImplicitlyUsedUnchecked(); + return InliningStatus_Inlined; +} + IonBuilder::InliningStatus IonBuilder::inlineIsTypedArrayHelper(CallInfo& callInfo, WrappingBehavior wrappingBehavior) { diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 5177492c747b..67df90a7149d 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -2169,7 +2169,8 @@ static const JSFunctionSpec intrinsic_functions[] = { intrinsic_IsInstanceOfBuiltin, 1,0), JS_FN("ArrayBufferByteLength", intrinsic_ArrayBufferByteLength, 1,0), - JS_FN("PossiblyWrappedArrayBufferByteLength", intrinsic_PossiblyWrappedArrayBufferByteLength, 1,0), + JS_INLINABLE_FN("PossiblyWrappedArrayBufferByteLength", intrinsic_PossiblyWrappedArrayBufferByteLength, 1,0, + IntrinsicPossiblyWrappedArrayBufferByteLength), JS_FN("ArrayBufferCopyData", intrinsic_ArrayBufferCopyData, 4,0), JS_FN("IsUint8TypedArray", intrinsic_IsUint8TypedArray, 1,0),