Bug 790051 - Add IonMonkey OOLNativeGetterExitFrame to support callouts to native getters from OOL IC stubs. (r=jandem)
authorKannan Vijayan <kvijayan@mozilla.com>
Wed, 26 Sep 2012 12:05:50 -0400
changeset 108150 5ebf745a3a40d1c489fab9fe95ad65fef8d18daf
parent 108149 29fe3da0ea11d3c6a050fc6fdf2e1a1fd4c17bd7
child 108151 0450cb4ef66ab6d4f23cb6868de8c87d0e08b783
push id23539
push userryanvm@gmail.com
push dateWed, 26 Sep 2012 22:55:55 +0000
treeherdermozilla-central@ec079fd92224 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs790051
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 790051 - Add IonMonkey OOLNativeGetterExitFrame to support callouts to native getters from OOL IC stubs. (r=jandem)
js/src/ion/IonFrameIterator.h
js/src/ion/IonFrames-inl.h
js/src/ion/IonFrames.cpp
js/src/ion/IonFrames.h
js/src/ion/arm/IonFrames-arm.h
js/src/ion/shared/IonFrames-shared.h
js/src/ion/shared/IonFrames-x86-shared.h
--- a/js/src/ion/IonFrameIterator.h
+++ b/js/src/ion/IonFrameIterator.h
@@ -108,16 +108,17 @@ class IonFrameIterator
     // places the invalidated Ion script in |ionScript|.
     bool checkInvalidation(IonScript **ionScript) const;
     bool checkInvalidation() const;
 
     bool isScripted() const {
         return type_ == IonFrame_JS;
     }
     bool isNative() const;
+    bool isOOLNativeGetter() const;
     bool isDOMExit() const;
     bool isEntry() const {
         return type_ == IonFrame_Entry;
     }
     bool isFunctionFrame() const;
 
     bool isConstructing() const;
 
--- a/js/src/ion/IonFrames-inl.h
+++ b/js/src/ion/IonFrames-inl.h
@@ -77,21 +77,30 @@ size_t
 IonFrameIterator::frameSize() const
 {
     JS_ASSERT(type_ != IonFrame_Exit);
     return frameSize_;
 }
 
 // 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<IonJSFrameLayout*>(iter.current());
     switch (GetCalleeTokenTag(frame->calleeToken())) {
       case CalleeToken_Function: {
         JSFunction *fun = CalleeTokenToFunction(frame->calleeToken());
         return fun->script();
       }
       case CalleeToken_Script:
--- a/js/src/ion/IonFrames.cpp
+++ b/js/src/ion/IonFrames.cpp
@@ -113,16 +113,24 @@ bool
 IonFrameIterator::isNative() const
 {
     if (type_ != IonFrame_Exit)
         return false;
     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
 {
     if (type_ != IonFrame_Exit)
         return false;
     return exitFrame()->isDomExit();
 }
 
 bool
@@ -525,16 +533,23 @@ MarkIonExitFrame(JSTracer *trc, const Io
     if (frame.isNative()) {
         IonNativeExitFrameLayout *native = frame.exitFrame()->nativeExit();
         size_t len = native->argc() + 2;
         Value *vp = native->vp();
         gc::MarkValueRootRange(trc, len, vp, "ion-native-args");
         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");
         if (dom->isSetterFrame()) {
             gc::MarkValueRoot(trc, dom->vp(), "ion-dom-args");
         } else if (dom->isMethodFrame()) {
             IonDOMMethodExitFrameLayout *method =
                 reinterpret_cast<IonDOMMethodExitFrameLayout *>(dom);
--- a/js/src/ion/IonFrames.h
+++ b/js/src/ion/IonFrames.h
@@ -252,17 +252,19 @@ MakeFrameDescriptor(uint32 frameSize, Fr
 #else
 # error "unsupported architecture"
 #endif
 
 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);
 
 // Given a slot index, returns the offset, in bytes, of that slot from an
 // IonJSFrameLayout. Slot distances are uniform across architectures, however,
 // the distance does depend on the size of the frame header.
 static inline int32
--- a/js/src/ion/arm/IonFrames-arm.h
+++ b/js/src/ion/arm/IonFrames-arm.h
@@ -151,16 +151,17 @@ class IonOsrFrameLayout : public IonJSFr
 {
   public:
     static inline size_t Size() {
         return sizeof(IonOsrFrameLayout);
     }
 };
 
 class IonNativeExitFrameLayout;
+class IonOOLNativeGetterExitFrameLayout;
 class IonDOMExitFrameLayout;
 
 // this is the frame layout when we are exiting ion code, and about to enter EABI code
 class IonExitFrameLayout : public IonCommonFrameLayout
 {
     inline uint8 *top() {
         return reinterpret_cast<uint8 *>(this + 1);
     }
@@ -187,29 +188,36 @@ class IonExitFrameLayout : public IonCom
     }
 
     inline bool isWrapperExit() {
         return footer()->function() != NULL;
     }
     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
             code == ION_FRAME_DOMGETTER ||
             code == ION_FRAME_DOMSETTER ||
             code == ION_FRAME_DOMMETHOD;
     }
 
     inline IonNativeExitFrameLayout *nativeExit() {
         // see CodeGenerator::visitCallNative
         JS_ASSERT(isNativeExit());
         return reinterpret_cast<IonNativeExitFrameLayout *>(footer());
     }
+    inline IonOOLNativeGetterExitFrameLayout *oolNativeGetterExit() {
+        JS_ASSERT(isOOLNativeGetterExit());
+        return reinterpret_cast<IonOOLNativeGetterExitFrameLayout *>(footer());
+    }
     inline IonDOMExitFrameLayout *DOMExit() {
         JS_ASSERT(isDomExit());
         return reinterpret_cast<IonDOMExitFrameLayout *>(footer());
     }
 };
 
 // Cannot inherit implementa<tion since we need to extend the top of
 // IonExitFrameLayout.
@@ -235,16 +243,46 @@ class IonNativeExitFrameLayout
     inline Value *vp() {
         return reinterpret_cast<Value*>(&loCalleeResult_);
     }
     inline uintptr_t argc() const {
         return argc_;
     }
 };
 
+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
 {
     IonExitFooterFrame footer_;
     IonExitFrameLayout exit_;
     JSObject *thisObj;
 
     // We need to split the Value in 2 field of 32 bits, otherwise the C++
     // compiler may add some padding between the fields.
--- a/js/src/ion/shared/IonFrames-shared.h
+++ b/js/src/ion/shared/IonFrames-shared.h
@@ -39,10 +39,11 @@
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef jsion_ionframes_shared_h__
 #define jsion_ionframes_shared_h__
 
 #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
--- a/js/src/ion/shared/IonFrames-x86-shared.h
+++ b/js/src/ion/shared/IonFrames-x86-shared.h
@@ -136,16 +136,17 @@ class IonExitFooterFrame
 
     // This should only be called for function()->outParam == Type_Handle
     Value *outVp() {
         return reinterpret_cast<Value *>(reinterpret_cast<char *>(this) - sizeof(Value));
     }
 };
 
 class IonNativeExitFrameLayout;
+class IonOOLNativeGetterExitFrameLayout;
 class IonDOMExitFrameLayout;
 
 class IonExitFrameLayout : public IonCommonFrameLayout
 {
     inline uint8 *top() {
         return reinterpret_cast<uint8 *>(this + 1);
     }
 
@@ -184,16 +185,21 @@ class IonExitFrameLayout : public IonCom
             code == ION_FRAME_DOMMETHOD;
     }
 
     inline IonNativeExitFrameLayout *nativeExit() {
         // see CodeGenerator::visitCallNative
         JS_ASSERT(isNativeExit());
         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() {
         JS_ASSERT(isDomExit());
         return reinterpret_cast<IonDOMExitFrameLayout *>(footer());
     }
 };
 
 class IonNativeExitFrameLayout
 {
@@ -218,16 +224,47 @@ class IonNativeExitFrameLayout
     inline Value *vp() {
         return reinterpret_cast<Value*>(&loCalleeResult_);
     }
     inline uintptr_t argc() const {
         return argc_;
     }
 };
 
+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
 {
   protected: // only to silence a clang warning about unused private fields
     IonExitFooterFrame footer_;
     IonExitFrameLayout exit_;
     JSObject *thisObj;
 
     // We need to split the Value in 2 field of 32 bits, otherwise the C++