From 8adaf120df6cd6228385dec05a0af629cf1e7908 Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Wed, 26 Sep 2012 12:05:50 -0400 Subject: [PATCH] Bug 790051 - Add IonMonkey OOLNativeGetterExitFrame to support callouts to native getters from OOL IC stubs. (r=jandem) --- js/src/ion/IonFrameIterator.h | 1 + js/src/ion/IonFrames-inl.h | 11 ++++++- js/src/ion/IonFrames.cpp | 15 ++++++++++ js/src/ion/IonFrames.h | 4 ++- js/src/ion/arm/IonFrames-arm.h | 38 ++++++++++++++++++++++++ js/src/ion/shared/IonFrames-shared.h | 1 + js/src/ion/shared/IonFrames-x86-shared.h | 37 +++++++++++++++++++++++ 7 files changed, 105 insertions(+), 2 deletions(-) diff --git a/js/src/ion/IonFrameIterator.h b/js/src/ion/IonFrameIterator.h index e1df640a5f8..93582bd0703 100644 --- a/js/src/ion/IonFrameIterator.h +++ b/js/src/ion/IonFrameIterator.h @@ -113,6 +113,7 @@ class IonFrameIterator return type_ == IonFrame_JS; } bool isNative() const; + bool isOOLNativeGetter() const; bool isDOMExit() const; bool isEntry() const { return type_ == IonFrame_Entry; diff --git a/js/src/ion/IonFrames-inl.h b/js/src/ion/IonFrames-inl.h index 875f9d9fd4f..41fbabe52e2 100644 --- a/js/src/ion/IonFrames-inl.h +++ b/js/src/ion/IonFrames-inl.h @@ -82,11 +82,20 @@ IonFrameIterator::frameSize() const // Returns the JSScript associated with the topmost Ion frame. inline JSScript * -GetTopIonJSScript(JSContext *cx) +GetTopIonJSScript(JSContext *cx, const SafepointIndex **safepointIndexOut, void **returnAddrOut) { IonFrameIterator iter(cx->runtime->ionTop); JS_ASSERT(iter.type() == IonFrame_Exit); ++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); IonJSFrameLayout *frame = static_cast(iter.current()); switch (GetCalleeTokenTag(frame->calleeToken())) { diff --git a/js/src/ion/IonFrames.cpp b/js/src/ion/IonFrames.cpp index 617340cd093..271a50ca0cb 100644 --- a/js/src/ion/IonFrames.cpp +++ b/js/src/ion/IonFrames.cpp @@ -117,6 +117,14 @@ IonFrameIterator::isNative() const 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 IonFrameIterator::isDOMExit() const { @@ -530,6 +538,13 @@ MarkIonExitFrame(JSTracer *trc, const IonFrameIterator &frame) 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()) { IonDOMExitFrameLayout *dom = frame.exitFrame()->DOMExit(); gc::MarkObjectRoot(trc, dom->thisObjAddress(), "ion-dom-args"); diff --git a/js/src/ion/IonFrames.h b/js/src/ion/IonFrames.h index 9a131203298..58c0c879001 100644 --- a/js/src/ion/IonFrames.h +++ b/js/src/ion/IonFrames.h @@ -257,7 +257,9 @@ namespace js { namespace ion { JSScript * -GetTopIonJSScript(JSContext *cx); +GetTopIonJSScript(JSContext *cx, + const SafepointIndex **safepointIndexOut = NULL, + void **returnAddrOut = NULL); void GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes); diff --git a/js/src/ion/arm/IonFrames-arm.h b/js/src/ion/arm/IonFrames-arm.h index f0cd1a5fb47..1b234fe33ef 100644 --- a/js/src/ion/arm/IonFrames-arm.h +++ b/js/src/ion/arm/IonFrames-arm.h @@ -156,6 +156,7 @@ class IonOsrFrameLayout : public IonJSFrameLayout }; class IonNativeExitFrameLayout; +class IonOOLNativeGetterExitFrameLayout; class IonDOMExitFrameLayout; // 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() { return footer()->ionCode() == NULL; } + inline bool isOOLNativeGetterExit() { + return footer()->ionCode() == ION_FRAME_OOL_NATIVE_GETTER; + } inline bool isDomExit() { IonCode *code = footer()->ionCode(); return @@ -205,6 +209,10 @@ class IonExitFrameLayout : public IonCommonFrameLayout JS_ASSERT(isNativeExit()); return reinterpret_cast(footer()); } + inline IonOOLNativeGetterExitFrameLayout *oolNativeGetterExit() { + JS_ASSERT(isOOLNativeGetterExit()); + return reinterpret_cast(footer()); + } inline IonDOMExitFrameLayout *DOMExit() { JS_ASSERT(isDomExit()); return reinterpret_cast(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(&loCalleeResult_); + } + inline uintptr_t argc() const { + return 0; + } +}; + class IonDOMExitFrameLayout { IonExitFooterFrame footer_; diff --git a/js/src/ion/shared/IonFrames-shared.h b/js/src/ion/shared/IonFrames-shared.h index cb0244d158b..76215575a38 100644 --- a/js/src/ion/shared/IonFrames-shared.h +++ b/js/src/ion/shared/IonFrames-shared.h @@ -44,5 +44,6 @@ #define ION_FRAME_DOMGETTER ((IonCode *)0x1) #define ION_FRAME_DOMSETTER ((IonCode *)0x2) #define ION_FRAME_DOMMETHOD ((IonCode *)0x3) +#define ION_FRAME_OOL_NATIVE_GETTER ((IonCode *)0x4) #endif diff --git a/js/src/ion/shared/IonFrames-x86-shared.h b/js/src/ion/shared/IonFrames-x86-shared.h index 9f63adf7ae5..49d4480b286 100644 --- a/js/src/ion/shared/IonFrames-x86-shared.h +++ b/js/src/ion/shared/IonFrames-x86-shared.h @@ -141,6 +141,7 @@ class IonExitFooterFrame }; class IonNativeExitFrameLayout; +class IonOOLNativeGetterExitFrameLayout; class IonDOMExitFrameLayout; class IonExitFrameLayout : public IonCommonFrameLayout @@ -189,6 +190,11 @@ class IonExitFrameLayout : public IonCommonFrameLayout JS_ASSERT(isNativeExit()); return reinterpret_cast(footer()); } + inline IonOOLNativeGetterExitFrameLayout *oolNativeGetterExit() { + // see CodeGenerator::visitCallNative + JS_ASSERT(footer()->ionCode() == ION_FRAME_OOL_NATIVE_GETTER); + return reinterpret_cast(footer()); + } inline IonDOMExitFrameLayout *DOMExit() { JS_ASSERT(isDomExit()); return reinterpret_cast(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(&loCalleeResult_); + } + inline uintptr_t argc() const { + return 0; + } +}; + class IonDOMExitFrameLayout { protected: // only to silence a clang warning about unused private fields