Commit 026df438 authored by Nicholas D. Matsakis's avatar Nicholas D. Matsakis
Browse files

Bug 977126 Part 3 -- Inline SetTypedObjectOffset intrinsic r=shu

parent cca3bd9e
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -2215,18 +2215,24 @@ TypedObject::obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
}

/* static */ size_t
TypedObject::ownerOffset()
TypedObject::offsetOfOwnerSlot()
{
    return JSObject::getFixedSlotOffset(JS_TYPEDOBJ_SLOT_OWNER);
}

/* static */ size_t
TypedObject::dataOffset()
TypedObject::offsetOfDataSlot()
{
    // the offset of 7 is based on the alloc kind
    return JSObject::getPrivateDataOffset(JS_TYPEDOBJ_SLOT_DATA);
}

/* static */ size_t
TypedObject::offsetOfByteOffsetSlot()
{
    return JSObject::getFixedSlotOffset(JS_TYPEDOBJ_SLOT_BYTEOFFSET);
}

void
TypedObject::neuter(void *newData)
{
@@ -2712,12 +2718,21 @@ js::SetTypedObjectOffset(ThreadSafeContext *, unsigned argc, Value *vp)

    typedObj.setPrivate(typedObj.owner().dataPointer() + offset);
    typedObj.setReservedSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET, Int32Value(offset));
    args.rval().setUndefined();
    return true;
}

JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::SetTypedObjectOffsetJitInfo,
bool
js::intrinsic_SetTypedObjectOffset(JSContext *cx, unsigned argc, Value *vp)
{
    // Do not use JSNativeThreadSafeWrapper<> so that ion can reference
    // this function more easily when inlining.
    return SetTypedObjectOffset(cx, argc, vp);
}

JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(js::intrinsic_SetTypedObjectOffsetJitInfo,
                                      SetTypedObjectJitInfo,
                                      js::SetTypedObjectOffset);
                                      SetTypedObjectOffset);

bool
js::ObjectIsTypeDescr(ThreadSafeContext *, unsigned argc, Value *vp)
+8 −4
Original line number Diff line number Diff line
@@ -585,7 +585,7 @@ class TypedObject : public ArrayBufferViewObject
                              MutableHandleValue statep, MutableHandleId idp);

  public:
    static size_t ownerOffset();
    static size_t offsetOfOwnerSlot();

    // Each typed object contains a void* pointer pointing at the
    // binary data that it represents. (That data may be owned by this
@@ -593,7 +593,10 @@ class TypedObject : public ArrayBufferViewObject
    // This function returns the offset in bytes within the object
    // where the `void*` pointer can be found. It is intended for use
    // by the JIT.
    static size_t dataOffset();
    static size_t offsetOfDataSlot();

    // Offset of the byte offset slot.
    static size_t offsetOfByteOffsetSlot();

    // Helper for createUnattached()
    static TypedObject *createUnattachedWithClass(JSContext *cx,
@@ -742,8 +745,9 @@ extern const JSJitInfo AttachTypedObjectJitInfo;
 * Changes the offset for `typedObj` within its buffer to `offset`.
 * `typedObj` must already be attached.
 */
bool SetTypedObjectOffset(ThreadSafeContext *cx, unsigned argc, Value *vp);
extern const JSJitInfo SetTypedObjectOffsetJitInfo;
bool intrinsic_SetTypedObjectOffset(JSContext *cx, unsigned argc, Value *vp);
bool SetTypedObjectOffset(ThreadSafeContext *, unsigned argc, Value *vp);
extern const JSJitInfo intrinsic_SetTypedObjectOffsetJitInfo;

/*
 * Usage: ObjectIsTypeDescr(obj)
+51 −2
Original line number Diff line number Diff line
@@ -4112,7 +4112,7 @@ CodeGenerator::visitNeuterCheck(LNeuterCheck *lir)
    Register obj = ToRegister(lir->object());
    Register temp = ToRegister(lir->temp());

    masm.extractObject(Address(obj, TypedObject::ownerOffset()), temp);
    masm.extractObject(Address(obj, TypedObject::offsetOfOwnerSlot()), temp);
    masm.unboxInt32(Address(temp, ArrayBufferObject::flagsOffset()), temp);
    masm.and32(Imm32(ArrayBufferObject::neuteredFlag()), temp);

@@ -4126,7 +4126,56 @@ CodeGenerator::visitTypedObjectElements(LTypedObjectElements *lir)
{
    Register obj = ToRegister(lir->object());
    Register out = ToRegister(lir->output());
    masm.loadPtr(Address(obj, TypedObject::dataOffset()), out);
    masm.loadPtr(Address(obj, TypedObject::offsetOfDataSlot()), out);
    return true;
}

bool
CodeGenerator::visitSetTypedObjectOffset(LSetTypedObjectOffset *lir)
{
    Register object = ToRegister(lir->object());
    Register offset = ToRegister(lir->offset());
    Register temp0 = ToRegister(lir->temp0());

    // `offset` is an absolute offset into the base buffer. One way
    // to implement this instruction would be load the base address
    // from the buffer and add `offset`. But that'd be an extra load.
    // We can instead load the current base pointer and current
    // offset, compute the difference with `offset`, and then adjust
    // the current base pointer. This is two loads but to adjacent
    // fields in the same object, which should come in the same cache
    // line.
    //
    // The C code I would probably write is the following:
    //
    // void SetTypedObjectOffset(TypedObject *obj, int32_t offset) {
    //     int32_t temp0 = obj->byteOffset;
    //     obj->pointer = obj->pointer - temp0 + offset;
    //     obj->byteOffset = offset;
    // }
    //
    // But what we actually compute is more like this, because it
    // saves us a temporary to do it this way:
    //
    // void SetTypedObjectOffset(TypedObject *obj, int32_t offset) {
    //     int32_t temp0 = obj->byteOffset;
    //     obj->pointer = obj->pointer - (temp0 - offset);
    //     obj->byteOffset = offset;
    // }

    // temp0 = typedObj->byteOffset;
    masm.unboxInt32(Address(object, TypedObject::offsetOfByteOffsetSlot()), temp0);

    // temp0 -= offset;
    masm.subPtr(offset, temp0);

    // obj->pointer -= temp0;
    masm.subPtr(temp0, Address(object, TypedObject::offsetOfDataSlot()));

    // obj->byteOffset = offset;
    masm.storeValue(JSVAL_TYPE_INT32, offset,
                    Address(object, TypedObject::offsetOfByteOffsetSlot()));

    return true;
}

+1 −0
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ class CodeGenerator : public CodeGeneratorSpecific
    bool visitTypedArrayElements(LTypedArrayElements *lir);
    bool visitNeuterCheck(LNeuterCheck *lir);
    bool visitTypedObjectElements(LTypedObjectElements *lir);
    bool visitSetTypedObjectOffset(LSetTypedObjectOffset *lir);
    bool visitStringLength(LStringLength *lir);
    bool visitInitializedLength(LInitializedLength *lir);
    bool visitSetInitializedLength(LSetInitializedLength *lir);
+1 −0
Original line number Diff line number Diff line
@@ -696,6 +696,7 @@ class IonBuilder : public MIRGenerator

    // TypedObject intrinsics.
    InliningStatus inlineObjectIsTypeDescr(CallInfo &callInfo);
    InliningStatus inlineSetTypedObjectOffset(CallInfo &callInfo);
    bool elementAccessIsTypedObjectArrayOfScalarType(MDefinition* obj, MDefinition* id,
                                                     ScalarTypeDescr::Type *arrayType);

Loading