Bug 790051 - Add IonMonkey OOLNativeGetterExitFrame to support callouts to native getters from OOL IC stubs. (r=jandem)

This commit is contained in:
Kannan Vijayan 2012-09-26 12:05:50 -04:00
parent 312412d741
commit 8adaf120df
7 changed files with 105 additions and 2 deletions

View File

@ -113,6 +113,7 @@ class IonFrameIterator
return type_ == IonFrame_JS; return type_ == IonFrame_JS;
} }
bool isNative() const; bool isNative() const;
bool isOOLNativeGetter() const;
bool isDOMExit() const; bool isDOMExit() const;
bool isEntry() const { bool isEntry() const {
return type_ == IonFrame_Entry; return type_ == IonFrame_Entry;

View File

@ -82,11 +82,20 @@ IonFrameIterator::frameSize() const
// Returns the JSScript associated with the topmost Ion frame. // Returns the JSScript associated with the topmost Ion frame.
inline JSScript * inline JSScript *
GetTopIonJSScript(JSContext *cx) GetTopIonJSScript(JSContext *cx, const SafepointIndex **safepointIndexOut, void **returnAddrOut)
{ {
IonFrameIterator iter(cx->runtime->ionTop); IonFrameIterator iter(cx->runtime->ionTop);
JS_ASSERT(iter.type() == IonFrame_Exit); JS_ASSERT(iter.type() == IonFrame_Exit);
++iter; ++iter;
// If needed, grab the safepoint index.
if (safepointIndexOut)
*safepointIndexOut = iter.safepoint();
JS_ASSERT(iter.returnAddressToFp() != NULL);
if (returnAddrOut)
*returnAddrOut = (void *) iter.returnAddressToFp();
JS_ASSERT(iter.type() == IonFrame_JS); JS_ASSERT(iter.type() == IonFrame_JS);
IonJSFrameLayout *frame = static_cast<IonJSFrameLayout*>(iter.current()); IonJSFrameLayout *frame = static_cast<IonJSFrameLayout*>(iter.current());
switch (GetCalleeTokenTag(frame->calleeToken())) { switch (GetCalleeTokenTag(frame->calleeToken())) {

View File

@ -117,6 +117,14 @@ IonFrameIterator::isNative() const
return exitFrame()->footer()->ionCode() == NULL; return exitFrame()->footer()->ionCode() == NULL;
} }
bool
IonFrameIterator::isOOLNativeGetter() const
{
if (type_ != IonFrame_Exit)
return false;
return exitFrame()->footer()->ionCode() == ION_FRAME_OOL_NATIVE_GETTER;
}
bool bool
IonFrameIterator::isDOMExit() const IonFrameIterator::isDOMExit() const
{ {
@ -530,6 +538,13 @@ MarkIonExitFrame(JSTracer *trc, const IonFrameIterator &frame)
return; return;
} }
if (frame.isOOLNativeGetter()) {
IonOOLNativeGetterExitFrameLayout *oolgetter = frame.exitFrame()->oolNativeGetterExit();
gc::MarkValueRoot(trc, oolgetter->vp(), "ion-ool-getter-callee");
gc::MarkValueRoot(trc, oolgetter->vp() + 1, "ion-ool-getter-this");
return;
}
if (frame.isDOMExit()) { if (frame.isDOMExit()) {
IonDOMExitFrameLayout *dom = frame.exitFrame()->DOMExit(); IonDOMExitFrameLayout *dom = frame.exitFrame()->DOMExit();
gc::MarkObjectRoot(trc, dom->thisObjAddress(), "ion-dom-args"); gc::MarkObjectRoot(trc, dom->thisObjAddress(), "ion-dom-args");

View File

@ -257,7 +257,9 @@ namespace js {
namespace ion { namespace ion {
JSScript * JSScript *
GetTopIonJSScript(JSContext *cx); GetTopIonJSScript(JSContext *cx,
const SafepointIndex **safepointIndexOut = NULL,
void **returnAddrOut = NULL);
void void
GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes); GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes);

View File

@ -156,6 +156,7 @@ class IonOsrFrameLayout : public IonJSFrameLayout
}; };
class IonNativeExitFrameLayout; class IonNativeExitFrameLayout;
class IonOOLNativeGetterExitFrameLayout;
class IonDOMExitFrameLayout; class IonDOMExitFrameLayout;
// this is the frame layout when we are exiting ion code, and about to enter EABI code // this is the frame layout when we are exiting ion code, and about to enter EABI code
@ -192,6 +193,9 @@ class IonExitFrameLayout : public IonCommonFrameLayout
inline bool isNativeExit() { inline bool isNativeExit() {
return footer()->ionCode() == NULL; return footer()->ionCode() == NULL;
} }
inline bool isOOLNativeGetterExit() {
return footer()->ionCode() == ION_FRAME_OOL_NATIVE_GETTER;
}
inline bool isDomExit() { inline bool isDomExit() {
IonCode *code = footer()->ionCode(); IonCode *code = footer()->ionCode();
return return
@ -205,6 +209,10 @@ class IonExitFrameLayout : public IonCommonFrameLayout
JS_ASSERT(isNativeExit()); JS_ASSERT(isNativeExit());
return reinterpret_cast<IonNativeExitFrameLayout *>(footer()); return reinterpret_cast<IonNativeExitFrameLayout *>(footer());
} }
inline IonOOLNativeGetterExitFrameLayout *oolNativeGetterExit() {
JS_ASSERT(isOOLNativeGetterExit());
return reinterpret_cast<IonOOLNativeGetterExitFrameLayout *>(footer());
}
inline IonDOMExitFrameLayout *DOMExit() { inline IonDOMExitFrameLayout *DOMExit() {
JS_ASSERT(isDomExit()); JS_ASSERT(isDomExit());
return reinterpret_cast<IonDOMExitFrameLayout *>(footer()); return reinterpret_cast<IonDOMExitFrameLayout *>(footer());
@ -240,6 +248,36 @@ class IonNativeExitFrameLayout
} }
}; };
class IonOOLNativeGetterExitFrameLayout
{
IonExitFooterFrame footer_;
IonExitFrameLayout exit_;
// We need to split the Value into 2 fields of 32 bits, otherwise the C++
// compiler may add some padding between the fields.
uint32_t loCalleeResult_;
uint32_t hiCalleeResult_;
// The frame includes the object argument.
uint32_t loThis_;
uint32_t hiThis_;
public:
static inline size_t Size() {
return sizeof(IonOOLNativeGetterExitFrameLayout);
}
static size_t offsetOfResult() {
return offsetof(IonOOLNativeGetterExitFrameLayout, loCalleeResult_);
}
inline Value *vp() {
return reinterpret_cast<Value*>(&loCalleeResult_);
}
inline uintptr_t argc() const {
return 0;
}
};
class IonDOMExitFrameLayout class IonDOMExitFrameLayout
{ {
IonExitFooterFrame footer_; IonExitFooterFrame footer_;

View File

@ -44,5 +44,6 @@
#define ION_FRAME_DOMGETTER ((IonCode *)0x1) #define ION_FRAME_DOMGETTER ((IonCode *)0x1)
#define ION_FRAME_DOMSETTER ((IonCode *)0x2) #define ION_FRAME_DOMSETTER ((IonCode *)0x2)
#define ION_FRAME_DOMMETHOD ((IonCode *)0x3) #define ION_FRAME_DOMMETHOD ((IonCode *)0x3)
#define ION_FRAME_OOL_NATIVE_GETTER ((IonCode *)0x4)
#endif #endif

View File

@ -141,6 +141,7 @@ class IonExitFooterFrame
}; };
class IonNativeExitFrameLayout; class IonNativeExitFrameLayout;
class IonOOLNativeGetterExitFrameLayout;
class IonDOMExitFrameLayout; class IonDOMExitFrameLayout;
class IonExitFrameLayout : public IonCommonFrameLayout class IonExitFrameLayout : public IonCommonFrameLayout
@ -189,6 +190,11 @@ class IonExitFrameLayout : public IonCommonFrameLayout
JS_ASSERT(isNativeExit()); JS_ASSERT(isNativeExit());
return reinterpret_cast<IonNativeExitFrameLayout *>(footer()); return reinterpret_cast<IonNativeExitFrameLayout *>(footer());
} }
inline IonOOLNativeGetterExitFrameLayout *oolNativeGetterExit() {
// see CodeGenerator::visitCallNative
JS_ASSERT(footer()->ionCode() == ION_FRAME_OOL_NATIVE_GETTER);
return reinterpret_cast<IonOOLNativeGetterExitFrameLayout *>(footer());
}
inline IonDOMExitFrameLayout *DOMExit() { inline IonDOMExitFrameLayout *DOMExit() {
JS_ASSERT(isDomExit()); JS_ASSERT(isDomExit());
return reinterpret_cast<IonDOMExitFrameLayout *>(footer()); return reinterpret_cast<IonDOMExitFrameLayout *>(footer());
@ -223,6 +229,37 @@ class IonNativeExitFrameLayout
} }
}; };
class IonOOLNativeGetterExitFrameLayout
{
IonExitFooterFrame footer_;
IonExitFrameLayout exit_;
// We need to split the Value into 2 fields of 32 bits, otherwise the C++
// compiler may add some padding between the fields.
uint32_t loCalleeResult_;
uint32_t hiCalleeResult_;
// The frame includes the object argument.
uint32_t loThisResult_;
uint32_t hiThisResult_;
public:
static inline size_t Size() {
return sizeof(IonOOLNativeGetterExitFrameLayout);
}
static size_t offsetOfResult() {
return offsetof(IonOOLNativeGetterExitFrameLayout, loCalleeResult_);
}
inline Value *vp() {
return reinterpret_cast<Value*>(&loCalleeResult_);
}
inline uintptr_t argc() const {
return 0;
}
};
class IonDOMExitFrameLayout class IonDOMExitFrameLayout
{ {
protected: // only to silence a clang warning about unused private fields protected: // only to silence a clang warning about unused private fields