Merge backout

This commit is contained in:
Chris Jones 2012-10-03 00:21:12 -07:00
commit 7b1217bbf7
24 changed files with 278 additions and 66 deletions

View File

@ -849,7 +849,29 @@ NS_IMETHODIMP
BluetoothAdapter::StopSendingFile(const nsAString& aDeviceAddress,
nsIDOMDOMRequest** aRequest)
{
// Will implement in another patch
BluetoothService* bs = BluetoothService::Get();
if (!bs) {
NS_WARNING("BluetoothService not available!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
if (!rs) {
NS_WARNING("No DOMRequest Service!");
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMDOMRequest> req;
nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(req));
if (NS_FAILED(rv)) {
NS_WARNING("Can't create DOMRequest!");
return NS_ERROR_FAILURE;
}
nsRefPtr<BluetoothVoidReplyRunnable> result = new BluetoothVoidReplyRunnable(req);
bs->StopSendingFile(aDeviceAddress, result);
req.forget(aRequest);
return NS_OK;
}

View File

@ -91,6 +91,8 @@ BluetoothOppManager::BluetoothOppManager() : mConnected(false)
, mRemoteObexVersion(0)
, mRemoteConnectionFlags(0)
, mRemoteMaxPacketLength(0)
, mAbortFlag(false)
, mReadFileThread(nullptr)
{
}
@ -171,7 +173,12 @@ BluetoothOppManager::SendFile(BlobParent* aActor,
bool
BluetoothOppManager::StopSendingFile(BluetoothReplyRunnable* aRunnable)
{
// will implement in another patch.
if (!mBlob) {
return false;
}
mAbortFlag = true;
return true;
}
@ -216,7 +223,14 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
return;
}
if (NS_FAILED(NS_NewThread(getter_AddRefs(mReadFileThread)))) {
NS_WARNING("Can't create thread");
SendDisconnectRequest();
return;
}
sSentFileSize = 0;
mAbortFlag = false;
sInstance->SendPutHeaderRequest(fileName, fileSize);
}
}
@ -227,19 +241,21 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
} else {
mConnected = false;
mBlob = nullptr;
mReadFileThread = nullptr;
}
} else if (mLastCommand == ObexRequestCode::Put) {
if (responseCode != ObexResponseCode::Continue) {
// FIXME: Needs error handling here
NS_WARNING("[OPP] Put failed");
} else {
nsCOMPtr<nsIThread> t;
NS_NewThread(getter_AddRefs(t));
if (mAbortFlag || mReadFileThread == nullptr) {
SendAbortRequest();
} else {
nsRefPtr<ReadFileTask> task = new ReadFileTask(mBlob);
nsRefPtr<ReadFileTask> task = new ReadFileTask(mBlob);
if (NS_FAILED(t->Dispatch(task, NS_DISPATCH_NORMAL))) {
NS_WARNING("Cannot dispatch ring task!");
if (NS_FAILED(mReadFileThread->Dispatch(task, NS_DISPATCH_NORMAL))) {
NS_WARNING("Cannot dispatch ring task!");
}
}
}
} else if (mLastCommand == ObexRequestCode::PutFinal) {
@ -249,6 +265,12 @@ BluetoothOppManager::ReceiveSocketData(UnixSocketRawData* aMessage)
} else {
SendDisconnectRequest();
}
} else if (mLastCommand == ObexRequestCode::Abort) {
if (responseCode != ObexResponseCode::Success) {
NS_WARNING("[OPP] Abort failed");
}
SendDisconnectRequest();
}
}
@ -359,3 +381,19 @@ BluetoothOppManager::SendDisconnectRequest()
memcpy(s->mData, req, s->mSize);
SendSocketData(s);
}
void
BluetoothOppManager::SendAbortRequest()
{
// Section 3.3.5 "Abort", IrOBEX 1.2
// [opcode:1][length:2][Headers:var]
uint8_t req[255];
int index = 3;
SetObexPacketInfo(req, ObexRequestCode::Abort, index);
mLastCommand = ObexRequestCode::Abort;
UnixSocketRawData* s = new UnixSocketRawData(index);
memcpy(s->mData, req, s->mSize);
SendSocketData(s);
}

View File

@ -57,6 +57,7 @@ public:
void SendPutRequest(uint8_t* aFileBody, int aFileBodyLength,
bool aFinal);
void SendDisconnectRequest();
void SendAbortRequest();
private:
BluetoothOppManager();
@ -67,8 +68,10 @@ private:
uint8_t mRemoteObexVersion;
uint8_t mRemoteConnectionFlags;
int mRemoteMaxPacketLength;
bool mAbortFlag;
nsCOMPtr<nsIDOMBlob> mBlob;
nsCOMPtr<nsIThread> mReadFileThread;
};
END_BLUETOOTH_NAMESPACE

View File

@ -286,6 +286,10 @@ public:
BlobChild* aBlobChild,
BluetoothReplyRunnable* aRunnable) = 0;
virtual bool
StopSendingFile(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable) = 0;
virtual nsresult
ListenSocketViaService(int aChannel,
BluetoothSocketType aType,

View File

@ -223,6 +223,8 @@ BluetoothParent::RecvPBluetoothRequestConstructor(
return actor->DoRequest(aRequest.get_DisconnectObjectPushRequest());
case Request::TSendFileRequest:
return actor->DoRequest(aRequest.get_SendFileRequest());
case Request::TStopSendingFileRequest:
return actor->DoRequest(aRequest.get_StopSendingFileRequest());
default:
MOZ_NOT_REACHED("Unknown type!");
return false;
@ -552,3 +554,13 @@ BluetoothRequestParent::DoRequest(const SendFileRequest& aRequest)
(BlobChild*)aRequest.blobChild(),
mReplyRunnable.get());
}
bool
BluetoothRequestParent::DoRequest(const StopSendingFileRequest& aRequest)
{
MOZ_ASSERT(mService);
MOZ_ASSERT(mRequestType == Request::TStopSendingFileRequest);
return mService->StopSendingFile(aRequest.devicePath(),
mReplyRunnable.get());
}

View File

@ -180,6 +180,9 @@ protected:
bool
DoRequest(const SendFileRequest& aRequest);
bool
DoRequest(const StopSendingFileRequest& aRequest);
};
END_BLUETOOTH_NAMESPACE

View File

@ -351,6 +351,16 @@ BluetoothServiceChildProcess::SendFile(
return true;
}
bool
BluetoothServiceChildProcess::StopSendingFile(
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable)
{
SendRequest(aRunnable,
StopSendingFileRequest(nsString(aDeviceAddress)));
return true;
}
nsresult
BluetoothServiceChildProcess::HandleStartup()
{

View File

@ -151,6 +151,10 @@ public:
BlobChild* aBlobChild,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
virtual bool
StopSendingFile(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
protected:
BluetoothServiceChildProcess();
virtual ~BluetoothServiceChildProcess();

View File

@ -122,6 +122,11 @@ struct SendFileRequest
PBlob blob;
};
struct StopSendingFileRequest
{
nsString devicePath;
};
union Request
{
DefaultAdapterPathRequest;
@ -143,6 +148,7 @@ union Request
DisconnectHeadsetRequest;
DisconnectObjectPushRequest;
SendFileRequest;
StopSendingFileRequest;
};
protocol PBluetooth

View File

@ -2423,6 +2423,20 @@ BluetoothDBusService::SendFile(const nsAString& aDeviceAddress,
return true;
}
bool
BluetoothDBusService::StopSendingFile(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable)
{
// Currently we only support one device sending one file at a time,
// so we don't need aDeviceAddress here because the target device
// has been determined when calling 'Connect()'. Nevertheless, keep
// it for future use.
BluetoothOppManager* opp = BluetoothOppManager::Get();
opp->StopSendingFile(aRunnable);
return true;
}
class ListenBluetoothSocketRunnable : public nsRunnable
{
public:

View File

@ -155,6 +155,10 @@ public:
BlobChild* aBlobChild,
BluetoothReplyRunnable* aRunnable);
virtual bool
StopSendingFile(const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable);
private:
nsresult SendGetPropertyMessage(const nsAString& aPath,
const char* aInterface,

View File

@ -780,8 +780,8 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
masm.j(Assembler::Above, &thunk);
// No argument fixup needed. Load the start of the target IonCode.
masm.movePtr(Address(objreg, offsetof(IonScript, method_)), objreg);
masm.movePtr(Address(objreg, IonCode::OffsetOfCode()), objreg);
masm.movePtr(Address(objreg, IonScript::offsetOfMethod()), objreg);
masm.movePtr(Address(objreg, IonCode::offsetOfCode()), objreg);
masm.jump(&makeCall);
// Argument fixed needed. Load the ArgumentsRectifier.
@ -789,7 +789,7 @@ CodeGenerator::visitCallGeneric(LCallGeneric *call)
{
JS_ASSERT(ArgumentsRectifierReg != objreg);
masm.movePtr(ImmGCPtr(argumentsRectifier), objreg); // Necessary for GC marking.
masm.movePtr(Address(objreg, IonCode::OffsetOfCode()), objreg);
masm.movePtr(Address(objreg, IonCode::offsetOfCode()), objreg);
masm.move32(Imm32(call->numStackArgs()), ArgumentsRectifierReg);
}
@ -855,8 +855,8 @@ CodeGenerator::visitCallKnown(LCallKnown *call)
masm.branchPtr(Assembler::BelowOrEqual, objreg, ImmWord(ION_COMPILING_SCRIPT), &invoke);
// Load the start of the target IonCode.
masm.movePtr(Address(objreg, offsetof(IonScript, method_)), objreg);
masm.movePtr(Address(objreg, IonCode::OffsetOfCode()), objreg);
masm.movePtr(Address(objreg, IonScript::offsetOfMethod()), objreg);
masm.movePtr(Address(objreg, IonCode::offsetOfCode()), objreg);
// Nestle the StackPointer up to the argument vector.
masm.freeStack(unusedStack);
@ -1098,8 +1098,8 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
// No argument fixup needed. Load the start of the target IonCode.
{
masm.movePtr(Address(objreg, offsetof(IonScript, method_)), objreg);
masm.movePtr(Address(objreg, IonCode::OffsetOfCode()), objreg);
masm.movePtr(Address(objreg, IonScript::offsetOfMethod()), objreg);
masm.movePtr(Address(objreg, IonCode::offsetOfCode()), objreg);
// Skip the construction of the rectifier frame because we have no
// underflow.
@ -1118,7 +1118,7 @@ CodeGenerator::visitApplyArgsGeneric(LApplyArgsGeneric *apply)
JS_ASSERT(ArgumentsRectifierReg != objreg);
masm.movePtr(ImmGCPtr(argumentsRectifier), objreg); // Necessary for GC marking.
masm.movePtr(Address(objreg, IonCode::OffsetOfCode()), objreg);
masm.movePtr(Address(objreg, IonCode::offsetOfCode()), objreg);
masm.movePtr(argcreg, ArgumentsRectifierReg);
}
@ -3141,6 +3141,13 @@ CodeGenerator::visitCache(LInstruction *ins)
if (!addOutOfLineCode(ool))
return false;
#if 0
// NOTE: This is currently disabled. OSI and IC interaction are protected
// through other means in ICs, since the nops incur significant overhead.
//
// ensureOsiSpace();
#endif
CodeOffsetJump jump = masm.jumpWithPatch(ool->repatchEntry());
CodeOffsetLabel label = masm.labelForPatch();
masm.bind(ool->rejoin());
@ -3945,6 +3952,10 @@ CodeGenerator::emitInstanceOf(LInstruction *ins, Register rhs)
if (!addOutOfLineCode(ool))
return false;
// If the IC code wants to patch, make sure there is enough space to that
// the patching does not overwrite an invalidation marker.
ensureOsiSpace();
CodeOffsetJump jump = masm.jumpWithPatch(ool->repatchEntry());
CodeOffsetLabel label = masm.labelForPatch();
masm.bind(ool->rejoin());

View File

@ -426,11 +426,13 @@ IonScript::IonScript()
scriptList_(0),
scriptEntries_(0),
refcount_(0),
slowCallCount(0),
recompileInfo_()
recompileInfo_(),
slowCallCount(0)
{
}
static const int DataAlignment = 4;
IonScript *
IonScript::New(JSContext *cx, uint32 frameSlots, uint32 frameSize, size_t snapshotsSize,
size_t bailoutEntries, size_t constants, size_t safepointIndices,
@ -724,6 +726,14 @@ IonScript::toggleBarriers(bool enabled)
void
IonScript::purgeCaches(JSCompartment *c)
{
// Don't reset any ICs if we're invalidated, otherwise, repointing the
// inline jump could overwrite an invalidation marker. These ICs can
// no longer run, however, the IC slow paths may be active on the stack.
// ICs therefore are required to check for invalidation before patching,
// to ensure the same invariant.
if (invalidated())
return;
// This is necessary because AutoFlushCache::updateTop()
// looks up the current flusher in the IonContext. Without one
// it cannot work.
@ -1479,6 +1489,13 @@ InvalidateActivation(FreeOp *fop, uint8 *ionTop, bool invalidateAll)
if (!invalidateAll && !script->ion->invalidated())
continue;
IonScript *ionScript = script->ion;
// Purge ICs before we mark this script as invalidated. This will
// prevent lastJump_ from appearing to be a bogus pointer, just
// in case anyone tries to read it.
ionScript->purgeCaches(script->compartment());
// This frame needs to be invalidated. We do the following:
//
// 1. Increment the reference counter to keep the ionScript alive
@ -1500,7 +1517,6 @@ InvalidateActivation(FreeOp *fop, uint8 *ionTop, bool invalidateAll)
// instructions after the call) in to capture an appropriate
// snapshot after the call occurs.
IonScript *ionScript = script->ion;
ionScript->incref();
const SafepointIndex *si = ionScript->getSafepointIndex(it.returnAddressToFp());

View File

@ -199,7 +199,8 @@ struct GetNativePropertyStub
};
bool
IonCacheGetProperty::attachNative(JSContext *cx, JSObject *obj, JSObject *holder, const Shape *shape)
IonCacheGetProperty::attachNative(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
const Shape *shape)
{
MacroAssembler masm;
RepatchLabel failures;
@ -215,6 +216,9 @@ IonCacheGetProperty::attachNative(JSContext *cx, JSObject *obj, JSObject *holder
getprop.rejoinOffset.fixup(&masm);
getprop.exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, getprop.rejoinOffset);
CodeLocationJump exitJump(code, getprop.exitOffset);
CodeLocationJump lastJump_ = lastJump();
@ -256,7 +260,8 @@ IsCacheableGetProp(JSObject *obj, JSObject *holder, const Shape *shape)
}
static bool
TryAttachNativeStub(JSContext *cx, IonCacheGetProperty &cache, HandleObject obj,
TryAttachNativeStub(JSContext *cx, IonScript *ion,
IonCacheGetProperty &cache, HandleObject obj,
HandlePropertyName name, bool *isCacheableNative)
{
JS_ASSERT(!*isCacheableNative);
@ -295,7 +300,7 @@ TryAttachNativeStub(JSContext *cx, IonCacheGetProperty &cache, HandleObject obj,
if (cache.stubCount() < MAX_STUBS) {
cache.incrementStubCount();
if (!cache.attachNative(cx, obj, holder, shape))
if (!cache.attachNative(cx, ion, obj, holder, shape))
return false;
}
@ -327,7 +332,7 @@ js::ion::GetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Mu
// limit. Once we can make calls from within generated stubs, a new call
// stub will be generated instead and the previous stubs unlinked.
bool isCacheableNative = false;
if (!TryAttachNativeStub(cx, cache, obj, name, &isCacheableNative))
if (!TryAttachNativeStub(cx, ion, cache, obj, name, &isCacheableNative))
return false;
if (cache.idempotent() && !isCacheableNative) {
@ -395,7 +400,7 @@ IonCache::reset()
}
bool
IonCacheSetProperty::attachNativeExisting(JSContext *cx, JSObject *obj, const Shape *shape)
IonCacheSetProperty::attachNativeExisting(JSContext *cx, IonScript *ion, JSObject *obj, const Shape *shape)
{
MacroAssembler masm;
@ -438,6 +443,9 @@ IonCacheSetProperty::attachNativeExisting(JSContext *cx, JSObject *obj, const Sh
rejoinOffset.fixup(&masm);
exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, rejoinOffset);
CodeLocationJump exitJump(code, exitOffset);
CodeLocationJump lastJump_ = lastJump();
@ -452,7 +460,8 @@ IonCacheSetProperty::attachNativeExisting(JSContext *cx, JSObject *obj, const Sh
}
bool
IonCacheSetProperty::attachNativeAdding(JSContext *cx, JSObject *obj, const Shape *oldShape, const Shape *newShape,
IonCacheSetProperty::attachNativeAdding(JSContext *cx, IonScript *ion, JSObject *obj,
const Shape *oldShape, const Shape *newShape,
const Shape *propShape)
{
MacroAssembler masm;
@ -525,6 +534,9 @@ IonCacheSetProperty::attachNativeAdding(JSContext *cx, JSObject *obj, const Shap
rejoinOffset.fixup(&masm);
exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, rejoinOffset);
CodeLocationJump exitJump(code, exitOffset);
CodeLocationJump lastJump_ = lastJump();
@ -639,7 +651,7 @@ js::ion::SetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Ha
bool inlinable = IsPropertyInlineable(obj, cache);
if (inlinable && IsPropertySetInlineable(cx, obj, name, &id, &shape)) {
cache.incrementStubCount();
if (!cache.attachNativeExisting(cx, obj, shape))
if (!cache.attachNativeExisting(cx, ion, obj, shape))
return false;
}
@ -655,7 +667,7 @@ js::ion::SetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Ha
if (inlinable && IsPropertyAddInlineable(cx, obj, id, oldSlots, &shape)) {
const Shape *newShape = obj->lastProperty();
cache.incrementStubCount();
if (!cache.attachNativeAdding(cx, obj, oldShape, newShape, shape))
if (!cache.attachNativeAdding(cx, ion, obj, oldShape, newShape, shape))
return false;
}
@ -663,7 +675,8 @@ js::ion::SetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Ha
}
bool
IonCacheGetElement::attachGetProp(JSContext *cx, HandleObject obj, const Value &idval, PropertyName *name)
IonCacheGetElement::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
const Value &idval, PropertyName *name)
{
RootedObject holder(cx);
RootedShape shape(cx);
@ -696,6 +709,9 @@ IonCacheGetElement::attachGetProp(JSContext *cx, HandleObject obj, const Value &
getprop.rejoinOffset.fixup(&masm);
getprop.exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, getprop.rejoinOffset);
CodeLocationJump exitJump(code, getprop.exitOffset);
CodeLocationJump lastJump_ = lastJump();
@ -721,7 +737,7 @@ GetDenseArrayShape(JSContext *cx, JSObject *globalObj)
}
bool
IonCacheGetElement::attachDenseArray(JSContext *cx, JSObject *obj, const Value &idval)
IonCacheGetElement::attachDenseArray(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval)
{
JS_ASSERT(obj->isDenseArray());
JS_ASSERT(idval.isInt32());
@ -782,6 +798,9 @@ IonCacheGetElement::attachDenseArray(JSContext *cx, JSObject *obj, const Value &
rejoinOffset.fixup(&masm);
exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, rejoinOffset);
CodeLocationJump exitJump(code, exitOffset);
CodeLocationJump lastJump_ = lastJump();
@ -819,14 +838,14 @@ js::ion::GetElementCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Han
uint32_t dummy;
if (idval.isString() && JSID_IS_ATOM(id) && !JSID_TO_ATOM(id)->isIndex(&dummy)) {
if (!cache.attachGetProp(cx, obj, idval, JSID_TO_ATOM(id)->asPropertyName()))
if (!cache.attachGetProp(cx, ion, obj, idval, JSID_TO_ATOM(id)->asPropertyName()))
return false;
}
} else if (!cache.hasDenseArrayStub() && obj->isDenseArray() && idval.isInt32()) {
// Generate at most one dense array stub.
cache.incrementStubCount();
if (!cache.attachDenseArray(cx, obj, idval))
if (!cache.attachDenseArray(cx, ion, obj, idval))
return false;
}
}
@ -844,7 +863,7 @@ js::ion::GetElementCache(JSContext *cx, size_t cacheIndex, HandleObject obj, Han
}
bool
IonCacheBindName::attachGlobal(JSContext *cx, JSObject *scopeChain)
IonCacheBindName::attachGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain)
{
JS_ASSERT(scopeChain->isGlobal());
@ -869,6 +888,9 @@ IonCacheBindName::attachGlobal(JSContext *cx, JSObject *scopeChain)
rejoinOffset.fixup(&masm);
exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, rejoinOffset);
CodeLocationJump exitJump(code, exitOffset);
CodeLocationJump lastJump_ = lastJump();
@ -930,7 +952,7 @@ GenerateScopeChainGuards(MacroAssembler &masm, JSObject *scopeChain, JSObject *h
}
bool
IonCacheBindName::attachNonGlobal(JSContext *cx, JSObject *scopeChain, JSObject *holder)
IonCacheBindName::attachNonGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain, JSObject *holder)
{
JS_ASSERT(IsCacheableNonGlobalScope(scopeChain));
@ -977,6 +999,9 @@ IonCacheBindName::attachNonGlobal(JSContext *cx, JSObject *scopeChain, JSObject
rejoinOffset.fixup(&masm);
exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, rejoinOffset);
CodeLocationJump exitJump(code, exitOffset);
CodeLocationJump lastJump_ = lastJump();
@ -1035,10 +1060,10 @@ js::ion::BindNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain
cache.incrementStubCount();
if (scopeChain->isGlobal()) {
if (!cache.attachGlobal(cx, scopeChain))
if (!cache.attachGlobal(cx, ion, scopeChain))
return NULL;
} else if (IsCacheableScopeChain(scopeChain, holder)) {
if (!cache.attachNonGlobal(cx, scopeChain, holder))
if (!cache.attachNonGlobal(cx, ion, scopeChain, holder))
return NULL;
} else {
IonSpew(IonSpew_InlineCaches, "BINDNAME uncacheable scope chain");
@ -1049,7 +1074,7 @@ js::ion::BindNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain
}
bool
IonCacheName::attach(JSContext *cx, HandleObject scopeChain, HandleObject holder, Shape *shape)
IonCacheName::attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject holder, Shape *shape)
{
MacroAssembler masm;
Label failures;
@ -1093,6 +1118,9 @@ IonCacheName::attach(JSContext *cx, HandleObject scopeChain, HandleObject holder
if (failures.bound())
exitOffset.fixup(&masm);
if (ion->invalidated())
return true;
CodeLocationJump rejoinJump(code, rejoinOffset);
CodeLocationJump lastJump_ = lastJump();
PatchJump(lastJump_, CodeLocationLabel(code));
@ -1168,7 +1196,7 @@ js::ion::GetNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
if (cache.stubCount() < MAX_STUBS &&
IsCacheableName(cx, scopeChain, obj, holder, shape))
{
if (!cache.attach(cx, scopeChain, obj, shape))
if (!cache.attach(cx, ion, scopeChain, obj, shape))
return false;
cache.incrementStubCount();
}

View File

@ -268,7 +268,8 @@ class IonCacheGetProperty : public IonCache
PropertyName *name() const { return u.getprop.name; }
TypedOrValueRegister output() const { return u.getprop.output.data(); }
bool attachNative(JSContext *cx, JSObject *obj, JSObject *holder, const Shape *shape);
bool attachNative(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
const Shape *shape);
};
class IonCacheSetProperty : public IonCache
@ -294,9 +295,9 @@ class IonCacheSetProperty : public IonCache
ConstantOrRegister value() const { return u.setprop.value.data(); }
bool strict() const { return u.setprop.strict; }
bool attachNativeExisting(JSContext *cx, JSObject *obj, const Shape *shape);
bool attachNativeAdding(JSContext *cx, JSObject *obj, const Shape *oldshape, const Shape *newshape,
const Shape *propshape);
bool attachNativeExisting(JSContext *cx, IonScript *ion, JSObject *obj, const Shape *shape);
bool attachNativeAdding(JSContext *cx, IonScript *ion, JSObject *obj, const Shape *oldshape,
const Shape *newshape, const Shape *propshape);
};
class IonCacheGetElement : public IonCache
@ -337,8 +338,8 @@ class IonCacheGetElement : public IonCache
u.getelem.hasDenseArrayStub = true;
}
bool attachGetProp(JSContext *cx, HandleObject obj, const Value &idval, PropertyName *name);
bool attachDenseArray(JSContext *cx, JSObject *obj, const Value &idval);
bool attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj, const Value &idval, PropertyName *name);
bool attachDenseArray(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
};
class IonCacheBindName : public IonCache
@ -367,8 +368,8 @@ class IonCacheBindName : public IonCache
return u.bindname.output;
}
bool attachGlobal(JSContext *cx, JSObject *scopeChain);
bool attachNonGlobal(JSContext *cx, JSObject *scopeChain, JSObject *holder);
bool attachGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain);
bool attachNonGlobal(JSContext *cx, IonScript *ion, JSObject *scopeChain, JSObject *holder);
};
class IonCacheName : public IonCache
@ -401,7 +402,8 @@ class IonCacheName : public IonCache
return kind_ == NameTypeOf;
}
bool attach(JSContext *cx, HandleObject scopeChain, HandleObject obj, Shape *shape);
bool attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject obj,
Shape *shape);
};
bool

View File

@ -105,7 +105,7 @@ class IonCode : public gc::Cell
return code;
}
static size_t OffsetOfCode() {
static size_t offsetOfCode() {
return offsetof(IonCode, code_);
}
@ -133,6 +133,7 @@ class IonCache;
// An IonScript attaches Ion-generated information to a JSScript.
struct IonScript
{
private:
// Code pointer containing the actual method.
HeapPtr<IonCode> method_;
@ -205,11 +206,12 @@ struct IonScript
// Number of references from invalidation records.
size_t refcount_;
types::RecompileInfo recompileInfo_;
public:
// Number of times this function has tried to call a non-IM compileable function
uint32 slowCallCount;
types::RecompileInfo recompileInfo_;
SnapshotOffset *bailoutTable() {
return (SnapshotOffset *)(reinterpret_cast<uint8 *>(this) + bailoutTable_);
}

View File

@ -481,7 +481,7 @@ MacroAssembler::performOsr()
// Get ionScript->method->code, and scoot to the osrEntry.
const Register code = ionScript;
loadPtr(Address(ionScript, IonScript::offsetOfMethod()), code);
loadPtr(Address(code, IonCode::OffsetOfCode()), code);
loadPtr(Address(code, IonCode::offsetOfCode()), code);
addPtr(osrEntry, code);
// To simplify stack handling, we create an intermediate OSR frame, that

View File

@ -324,8 +324,8 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
// Note that this code assumes the function is JITted.
masm.ma_ldr(DTRAddr(r1, DtrOffImm(offsetof(JSFunction, u.i.script_))), r3);
masm.ma_ldr(DTRAddr(r3, DtrOffImm(offsetof(JSScript, ion))), r3);
masm.ma_ldr(DTRAddr(r3, DtrOffImm(offsetof(IonScript, method_))), r3);
masm.ma_ldr(DTRAddr(r3, DtrOffImm(IonCode::OffsetOfCode())), r3);
masm.ma_ldr(DTRAddr(r3, DtrOffImm(IonScript::offsetOfMethod())), r3);
masm.ma_ldr(DTRAddr(r3, DtrOffImm(IonCode::offsetOfCode())), r3);
masm.ma_callIonHalfPush(r3);
// arg1

View File

@ -308,15 +308,24 @@ CodeGeneratorShared::markSafepointAt(uint32 offset, LInstruction *ins)
return safepointIndices_.append(SafepointIndex(offset, ins->safepoint()));
}
bool
CodeGeneratorShared::markOsiPoint(LOsiPoint *ins, uint32 *callPointOffset)
void
CodeGeneratorShared::ensureOsiSpace()
{
if (!encode(ins->snapshot()))
return false;
// We need to ensure that two OSI point patches don't overlap with
// each other, so we check that there's enough space for the near
// call between any two OSI points.
// For a refresher, an invalidation point is of the form:
// 1: call <target>
// 2: ...
// 3: <osipoint>
//
// The four bytes *before* instruction 2 are overwritten with an offset.
// Callers must ensure that the instruction itself has enough bytes to
// support this.
//
// The bytes *at* instruction 3 are overwritten with an invalidation jump.
// jump. These bytes may be in a completely different IR sequence, but
// represent the join point of the call out of the function.
//
// At points where we want to ensure that invalidation won't corrupt an
// important instruction, we make sure to pad with nops.
if (masm.currentOffset() - lastOsiPointOffset_ < Assembler::patchWrite_NearCallSize()) {
int32 paddingSize = Assembler::patchWrite_NearCallSize();
paddingSize -= masm.currentOffset() - lastOsiPointOffset_;
@ -325,6 +334,15 @@ CodeGeneratorShared::markOsiPoint(LOsiPoint *ins, uint32 *callPointOffset)
}
JS_ASSERT(masm.currentOffset() - lastOsiPointOffset_ >= Assembler::patchWrite_NearCallSize());
lastOsiPointOffset_ = masm.currentOffset();
}
bool
CodeGeneratorShared::markOsiPoint(LOsiPoint *ins, uint32 *callPointOffset)
{
if (!encode(ins->snapshot()))
return false;
ensureOsiSpace();
*callPointOffset = masm.currentOffset();
SnapshotOffset so = ins->snapshot()->snapshotOffset();

View File

@ -190,6 +190,13 @@ class CodeGeneratorShared : public LInstructionVisitor
// |returnPointOffset|.
bool markOsiPoint(LOsiPoint *ins, uint32 *returnPointOffset);
// Ensure that there is enough room between the last OSI point and the
// current instruction, such that:
// (1) Invalidation will not overwrite the current instruction, and
// (2) Overwriting the current instruction will not overwrite
// an invalidation marker.
void ensureOsiSpace();
bool emitTruncateDouble(const FloatRegister &src, const Register &dest);
void emitPreBarrier(Register base, const LAllocation *index, MIRType type);

View File

@ -277,8 +277,8 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
// Note that this code assumes the function is JITted.
masm.movq(Operand(rax, offsetof(JSFunction, u.i.script_)), rax);
masm.movq(Operand(rax, offsetof(JSScript, ion)), rax);
masm.movq(Operand(rax, offsetof(IonScript, method_)), rax);
masm.movq(Operand(rax, IonCode::OffsetOfCode()), rax);
masm.movq(Operand(rax, IonScript::offsetOfMethod()), rax);
masm.movq(Operand(rax, IonCode::offsetOfCode()), rax);
masm.call(rax);
// Remove the rectifier frame.

View File

@ -182,6 +182,14 @@ namespace ion {
static inline void
PatchJump(CodeLocationJump jump, CodeLocationLabel label)
{
#ifdef DEBUG
// Assert that we're overwriting a jump instruction, either:
// 0F 80+cc <imm32>, or
// E9 <imm32>
unsigned char *x = (unsigned char *)jump.raw() - 5;
JS_ASSERT(((*x >= 0x80 && *x <= 0x8F) && *(x - 1) == 0x0F) ||
(*x == 0xE9));
#endif
JSC::X86Assembler::setRel32(jump.raw(), label.raw());
}

View File

@ -283,8 +283,8 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
// Note that this assumes the function is JITted.
masm.movl(Operand(eax, offsetof(JSFunction, u.i.script_)), eax);
masm.movl(Operand(eax, offsetof(JSScript, ion)), eax);
masm.movl(Operand(eax, offsetof(IonScript, method_)), eax);
masm.movl(Operand(eax, IonCode::OffsetOfCode()), eax);
masm.movl(Operand(eax, IonScript::offsetOfMethod()), eax);
masm.movl(Operand(eax, IonCode::offsetOfCode()), eax);
masm.call(eax);
// Remove the rectifier frame.

View File

@ -707,10 +707,10 @@ class CallCompiler : public BaseCompiler
/* Call into Ion. */
masm.loadPtr(Address(ionScript, ion::IonScript::offsetOfMethod()), t0);
#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
masm.loadPtr(Address(t0, ion::IonCode::OffsetOfCode()), t0);
masm.loadPtr(Address(t0, ion::IonCode::offsetOfCode()), t0);
masm.call(t0);
#elif defined(JS_CPU_ARM)
masm.loadPtr(Address(t0, ion::IonCode::OffsetOfCode()), JSC::ARMRegisters::ip);
masm.loadPtr(Address(t0, ion::IonCode::offsetOfCode()), JSC::ARMRegisters::ip);
masm.callAddress(JS_FUNC_TO_DATA_PTR(void *, IonVeneer));
#endif