js/src/jit/IonFrames.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef jit_IonFrames_h
     8 #define jit_IonFrames_h
    10 #ifdef JS_ION
    12 #include <stdint.h>
    14 #include "jscntxt.h"
    15 #include "jsfun.h"
    17 #include "jit/JitFrameIterator.h"
    19 namespace js {
    20 namespace jit {
    22 typedef void * CalleeToken;
    24 enum CalleeTokenTag
    25 {
    26     CalleeToken_Function = 0x0, // untagged
    27     CalleeToken_Script = 0x1
    28 };
    30 static inline CalleeTokenTag
    31 GetCalleeTokenTag(CalleeToken token)
    32 {
    33     CalleeTokenTag tag = CalleeTokenTag(uintptr_t(token) & 0x3);
    34     JS_ASSERT(tag <= CalleeToken_Script);
    35     return tag;
    36 }
    37 static inline CalleeToken
    38 CalleeToToken(JSFunction *fun)
    39 {
    40     return CalleeToken(uintptr_t(fun) | uintptr_t(CalleeToken_Function));
    41 }
    42 static inline CalleeToken
    43 CalleeToToken(JSScript *script)
    44 {
    45     return CalleeToken(uintptr_t(script) | uintptr_t(CalleeToken_Script));
    46 }
    47 static inline bool
    48 CalleeTokenIsFunction(CalleeToken token)
    49 {
    50     return GetCalleeTokenTag(token) == CalleeToken_Function;
    51 }
    52 static inline JSFunction *
    53 CalleeTokenToFunction(CalleeToken token)
    54 {
    55     JS_ASSERT(CalleeTokenIsFunction(token));
    56     return (JSFunction *)token;
    57 }
    58 static inline JSScript *
    59 CalleeTokenToScript(CalleeToken token)
    60 {
    61     JS_ASSERT(GetCalleeTokenTag(token) == CalleeToken_Script);
    62     return (JSScript *)(uintptr_t(token) & ~uintptr_t(0x3));
    63 }
    65 static inline JSScript *
    66 ScriptFromCalleeToken(CalleeToken token)
    67 {
    68     switch (GetCalleeTokenTag(token)) {
    69       case CalleeToken_Script:
    70         return CalleeTokenToScript(token);
    71       case CalleeToken_Function:
    72         return CalleeTokenToFunction(token)->nonLazyScript();
    73     }
    74     MOZ_ASSUME_UNREACHABLE("invalid callee token tag");
    75 }
    77 // In between every two frames lies a small header describing both frames. This
    78 // header, minimally, contains a returnAddress word and a descriptor word. The
    79 // descriptor describes the size and type of the previous frame, whereas the
    80 // returnAddress describes the address the newer frame (the callee) will return
    81 // to. The exact mechanism in which frames are laid out is architecture
    82 // dependent.
    83 //
    84 // Two special frame types exist. Entry frames begin an ion activation, and
    85 // therefore there is exactly one per activation of jit::Cannon. Exit frames
    86 // are necessary to leave JIT code and enter C++, and thus, C++ code will
    87 // always begin iterating from the topmost exit frame.
    89 class LSafepoint;
    91 // Two-tuple that lets you look up the safepoint entry given the
    92 // displacement of a call instruction within the JIT code.
    93 class SafepointIndex
    94 {
    95     // The displacement is the distance from the first byte of the JIT'd code
    96     // to the return address (of the call that the safepoint was generated for).
    97     uint32_t displacement_;
    99     union {
   100         LSafepoint *safepoint_;
   102         // Offset to the start of the encoded safepoint in the safepoint stream.
   103         uint32_t safepointOffset_;
   104     };
   106 #ifdef DEBUG
   107     bool resolved;
   108 #endif
   110   public:
   111     SafepointIndex(uint32_t displacement, LSafepoint *safepoint)
   112       : displacement_(displacement),
   113         safepoint_(safepoint)
   114 #ifdef DEBUG
   115       , resolved(false)
   116 #endif
   117     { }
   119     void resolve();
   121     LSafepoint *safepoint() {
   122         JS_ASSERT(!resolved);
   123         return safepoint_;
   124     }
   125     uint32_t displacement() const {
   126         return displacement_;
   127     }
   128     uint32_t safepointOffset() const {
   129         return safepointOffset_;
   130     }
   131     void adjustDisplacement(uint32_t offset) {
   132         JS_ASSERT(offset >= displacement_);
   133         displacement_ = offset;
   134     }
   135     inline SnapshotOffset snapshotOffset() const;
   136     inline bool hasSnapshotOffset() const;
   137 };
   139 class MacroAssembler;
   140 // The OSI point is patched to a call instruction. Therefore, the
   141 // returnPoint for an OSI call is the address immediately following that
   142 // call instruction. The displacement of that point within the assembly
   143 // buffer is the |returnPointDisplacement|.
   144 class OsiIndex
   145 {
   146     uint32_t callPointDisplacement_;
   147     uint32_t snapshotOffset_;
   149   public:
   150     OsiIndex(uint32_t callPointDisplacement, uint32_t snapshotOffset)
   151       : callPointDisplacement_(callPointDisplacement),
   152         snapshotOffset_(snapshotOffset)
   153     { }
   155     uint32_t returnPointDisplacement() const;
   156     uint32_t callPointDisplacement() const {
   157         return callPointDisplacement_;
   158     }
   159     uint32_t snapshotOffset() const {
   160         return snapshotOffset_;
   161     }
   162     void fixUpOffset(MacroAssembler &masm);
   163 };
   165 // The layout of an Ion frame on the C stack is roughly:
   166 //      argN     _
   167 //      ...       \ - These are jsvals
   168 //      arg0      /
   169 //   -3 this    _/
   170 //   -2 callee
   171 //   -1 descriptor
   172 //    0 returnAddress
   173 //   .. locals ..
   175 // The descriptor is organized into three sections:
   176 // [ frame size | constructing bit | frame type ]
   177 // < highest - - - - - - - - - - - - - - lowest >
   178 static const uintptr_t FRAMESIZE_SHIFT = 4;
   179 static const uintptr_t FRAMETYPE_BITS = 4;
   180 static const uintptr_t FRAMETYPE_MASK = (1 << FRAMETYPE_BITS) - 1;
   182 // Ion frames have a few important numbers associated with them:
   183 //      Local depth:    The number of bytes required to spill local variables.
   184 //      Argument depth: The number of bytes required to push arguments and make
   185 //                      a function call.
   186 //      Slack:          A frame may temporarily use extra stack to resolve cycles.
   187 //
   188 // The (local + argument) depth determines the "fixed frame size". The fixed
   189 // frame size is the distance between the stack pointer and the frame header.
   190 // Thus, fixed >= (local + argument).
   191 //
   192 // In order to compress guards, we create shared jump tables that recover the
   193 // script from the stack and recover a snapshot pointer based on which jump was
   194 // taken. Thus, we create a jump table for each fixed frame size.
   195 //
   196 // Jump tables are big. To control the amount of jump tables we generate, each
   197 // platform chooses how to segregate stack size classes based on its
   198 // architecture.
   199 //
   200 // On some architectures, these jump tables are not used at all, or frame
   201 // size segregation is not needed. Thus, there is an option for a frame to not
   202 // have any frame size class, and to be totally dynamic.
   203 static const uint32_t NO_FRAME_SIZE_CLASS_ID = uint32_t(-1);
   205 class FrameSizeClass
   206 {
   207     uint32_t class_;
   209     explicit FrameSizeClass(uint32_t class_) : class_(class_)
   210     { }
   212   public:
   213     FrameSizeClass()
   214     { }
   216     static FrameSizeClass None() {
   217         return FrameSizeClass(NO_FRAME_SIZE_CLASS_ID);
   218     }
   219     static FrameSizeClass FromClass(uint32_t class_) {
   220         return FrameSizeClass(class_);
   221     }
   223     // These functions are implemented in specific CodeGenerator-* files.
   224     static FrameSizeClass FromDepth(uint32_t frameDepth);
   225     static FrameSizeClass ClassLimit();
   226     uint32_t frameSize() const;
   228     uint32_t classId() const {
   229         JS_ASSERT(class_ != NO_FRAME_SIZE_CLASS_ID);
   230         return class_;
   231     }
   233     bool operator ==(const FrameSizeClass &other) const {
   234         return class_ == other.class_;
   235     }
   236     bool operator !=(const FrameSizeClass &other) const {
   237         return class_ != other.class_;
   238     }
   239 };
   241 struct BaselineBailoutInfo;
   243 // Data needed to recover from an exception.
   244 struct ResumeFromException
   245 {
   246     static const uint32_t RESUME_ENTRY_FRAME = 0;
   247     static const uint32_t RESUME_CATCH = 1;
   248     static const uint32_t RESUME_FINALLY = 2;
   249     static const uint32_t RESUME_FORCED_RETURN = 3;
   250     static const uint32_t RESUME_BAILOUT = 4;
   252     uint8_t *framePointer;
   253     uint8_t *stackPointer;
   254     uint8_t *target;
   255     uint32_t kind;
   257     // Value to push when resuming into a |finally| block.
   258     Value exception;
   260     BaselineBailoutInfo *bailoutInfo;
   261 };
   263 void HandleException(ResumeFromException *rfe);
   264 void HandleParallelFailure(ResumeFromException *rfe);
   266 void EnsureExitFrame(IonCommonFrameLayout *frame);
   268 void MarkJitActivations(JSRuntime *rt, JSTracer *trc);
   269 void MarkIonCompilerRoots(JSTracer *trc);
   271 #ifdef JSGC_GENERATIONAL
   272 void UpdateJitActivationsForMinorGC(JSRuntime *rt, JSTracer *trc);
   273 #endif
   275 static inline uint32_t
   276 MakeFrameDescriptor(uint32_t frameSize, FrameType type)
   277 {
   278     return (frameSize << FRAMESIZE_SHIFT) | type;
   279 }
   281 // Returns the JSScript associated with the topmost Ion frame.
   282 inline JSScript *
   283 GetTopIonJSScript(uint8_t *ionTop, void **returnAddrOut, ExecutionMode mode)
   284 {
   285     JitFrameIterator iter(ionTop, mode);
   286     JS_ASSERT(iter.type() == JitFrame_Exit);
   287     ++iter;
   289     JS_ASSERT(iter.returnAddressToFp() != nullptr);
   290     if (returnAddrOut)
   291         *returnAddrOut = (void *) iter.returnAddressToFp();
   293     if (iter.isBaselineStub()) {
   294         ++iter;
   295         JS_ASSERT(iter.isBaselineJS());
   296     }
   298     JS_ASSERT(iter.isScripted());
   299     return iter.script();
   300 }
   302 static JitCode *const ION_FRAME_DOMGETTER       = (JitCode *)0x1;
   303 static JitCode *const ION_FRAME_DOMSETTER       = (JitCode *)0x2;
   304 static JitCode *const ION_FRAME_DOMMETHOD       = (JitCode *)0x3;
   305 static JitCode *const ION_FRAME_OOL_NATIVE      = (JitCode *)0x4;
   306 static JitCode *const ION_FRAME_OOL_PROPERTY_OP = (JitCode *)0x5;
   307 static JitCode *const ION_FRAME_OOL_PROXY       = (JitCode *)0x6;
   309 // Layout of the frame prefix. This assumes the stack architecture grows down.
   310 // If this is ever not the case, we'll have to refactor.
   311 class IonCommonFrameLayout
   312 {
   313     uint8_t *returnAddress_;
   314     uintptr_t descriptor_;
   316     static const uintptr_t FrameTypeMask = (1 << FRAMETYPE_BITS) - 1;
   318   public:
   319     static size_t offsetOfDescriptor() {
   320         return offsetof(IonCommonFrameLayout, descriptor_);
   321     }
   322     static size_t offsetOfReturnAddress() {
   323         return offsetof(IonCommonFrameLayout, returnAddress_);
   324     }
   325     FrameType prevType() const {
   326         return FrameType(descriptor_ & FrameTypeMask);
   327     }
   328     void changePrevType(FrameType type) {
   329         descriptor_ &= ~FrameTypeMask;
   330         descriptor_ |= type;
   331     }
   332     size_t prevFrameLocalSize() const {
   333         return descriptor_ >> FRAMESIZE_SHIFT;
   334     }
   335     void setFrameDescriptor(size_t size, FrameType type) {
   336         descriptor_ = (size << FRAMESIZE_SHIFT) | type;
   337     }
   338     uint8_t *returnAddress() const {
   339         return returnAddress_;
   340     }
   341     void setReturnAddress(uint8_t *addr) {
   342         returnAddress_ = addr;
   343     }
   344 };
   346 class IonJSFrameLayout : public IonCommonFrameLayout
   347 {
   348     CalleeToken calleeToken_;
   349     uintptr_t numActualArgs_;
   351   public:
   352     CalleeToken calleeToken() const {
   353         return calleeToken_;
   354     }
   355     void replaceCalleeToken(CalleeToken calleeToken) {
   356         calleeToken_ = calleeToken;
   357     }
   359     static size_t offsetOfCalleeToken() {
   360         return offsetof(IonJSFrameLayout, calleeToken_);
   361     }
   362     static size_t offsetOfNumActualArgs() {
   363         return offsetof(IonJSFrameLayout, numActualArgs_);
   364     }
   365     static size_t offsetOfThis() {
   366         IonJSFrameLayout *base = nullptr;
   367         return reinterpret_cast<size_t>(&base->argv()[0]);
   368     }
   369     static size_t offsetOfActualArgs() {
   370         IonJSFrameLayout *base = nullptr;
   371         // +1 to skip |this|.
   372         return reinterpret_cast<size_t>(&base->argv()[1]);
   373     }
   374     static size_t offsetOfActualArg(size_t arg) {
   375         return offsetOfActualArgs() + arg * sizeof(Value);
   376     }
   378     Value thisv() {
   379         return argv()[0];
   380     }
   381     Value *argv() {
   382         return (Value *)(this + 1);
   383     }
   384     uintptr_t numActualArgs() const {
   385         return numActualArgs_;
   386     }
   388     // Computes a reference to a slot, where a slot is a distance from the base
   389     // frame pointer (as would be used for LStackSlot).
   390     uintptr_t *slotRef(uint32_t slot) {
   391         return (uintptr_t *)((uint8_t *)this - slot);
   392     }
   394     static inline size_t Size() {
   395         return sizeof(IonJSFrameLayout);
   396     }
   397 };
   399 // this is the layout of the frame that is used when we enter Ion code from platform ABI code
   400 class IonEntryFrameLayout : public IonJSFrameLayout
   401 {
   402   public:
   403     static inline size_t Size() {
   404         return sizeof(IonEntryFrameLayout);
   405     }
   406 };
   408 class IonRectifierFrameLayout : public IonJSFrameLayout
   409 {
   410   public:
   411     static inline size_t Size() {
   412         return sizeof(IonRectifierFrameLayout);
   413     }
   414 };
   416 // The callee token is now dead.
   417 class IonUnwoundRectifierFrameLayout : public IonRectifierFrameLayout
   418 {
   419   public:
   420     static inline size_t Size() {
   421         // It is not necessary to accout for an extra callee token here because
   422         // sizeof(IonExitFrameLayout) == sizeof(IonRectifierFrameLayout) due to
   423         // extra padding.
   424         return sizeof(IonUnwoundRectifierFrameLayout);
   425     }
   426 };
   428 // GC related data used to keep alive data surrounding the Exit frame.
   429 class IonExitFooterFrame
   430 {
   431     const VMFunction *function_;
   432     JitCode *jitCode_;
   434   public:
   435     static inline size_t Size() {
   436         return sizeof(IonExitFooterFrame);
   437     }
   438     inline JitCode *jitCode() const {
   439         return jitCode_;
   440     }
   441     inline JitCode **addressOfJitCode() {
   442         return &jitCode_;
   443     }
   444     inline const VMFunction *function() const {
   445         return function_;
   446     }
   448     // This should only be called for function()->outParam == Type_Handle
   449     template <typename T>
   450     T *outParam() {
   451         return reinterpret_cast<T *>(reinterpret_cast<char *>(this) - sizeof(T));
   452     }
   453 };
   455 class IonNativeExitFrameLayout;
   456 class IonOOLNativeExitFrameLayout;
   457 class IonOOLPropertyOpExitFrameLayout;
   458 class IonOOLProxyExitFrameLayout;
   459 class IonDOMExitFrameLayout;
   461 // this is the frame layout when we are exiting ion code, and about to enter platform ABI code
   462 class IonExitFrameLayout : public IonCommonFrameLayout
   463 {
   464     inline uint8_t *top() {
   465         return reinterpret_cast<uint8_t *>(this + 1);
   466     }
   468   public:
   469     static inline size_t Size() {
   470         return sizeof(IonExitFrameLayout);
   471     }
   472     static inline size_t SizeWithFooter() {
   473         return Size() + IonExitFooterFrame::Size();
   474     }
   476     inline IonExitFooterFrame *footer() {
   477         uint8_t *sp = reinterpret_cast<uint8_t *>(this);
   478         return reinterpret_cast<IonExitFooterFrame *>(sp - IonExitFooterFrame::Size());
   479     }
   481     // argBase targets the point which precedes the exit frame. Arguments of VM
   482     // each wrapper are pushed before the exit frame.  This correspond exactly
   483     // to the value of the argBase register of the generateVMWrapper function.
   484     inline uint8_t *argBase() {
   485         JS_ASSERT(footer()->jitCode() != nullptr);
   486         return top();
   487     }
   489     inline bool isWrapperExit() {
   490         return footer()->function() != nullptr;
   491     }
   492     inline bool isNativeExit() {
   493         return footer()->jitCode() == nullptr;
   494     }
   495     inline bool isOOLNativeExit() {
   496         return footer()->jitCode() == ION_FRAME_OOL_NATIVE;
   497     }
   498     inline bool isOOLPropertyOpExit() {
   499         return footer()->jitCode() == ION_FRAME_OOL_PROPERTY_OP;
   500     }
   501     inline bool isOOLProxyExit() {
   502         return footer()->jitCode() == ION_FRAME_OOL_PROXY;
   503     }
   504     inline bool isDomExit() {
   505         JitCode *code = footer()->jitCode();
   506         return
   507             code == ION_FRAME_DOMGETTER ||
   508             code == ION_FRAME_DOMSETTER ||
   509             code == ION_FRAME_DOMMETHOD;
   510     }
   512     inline IonNativeExitFrameLayout *nativeExit() {
   513         // see CodeGenerator::visitCallNative
   514         JS_ASSERT(isNativeExit());
   515         return reinterpret_cast<IonNativeExitFrameLayout *>(footer());
   516     }
   517     inline IonOOLNativeExitFrameLayout *oolNativeExit() {
   518         JS_ASSERT(isOOLNativeExit());
   519         return reinterpret_cast<IonOOLNativeExitFrameLayout *>(footer());
   520     }
   521     inline IonOOLPropertyOpExitFrameLayout *oolPropertyOpExit() {
   522         JS_ASSERT(isOOLPropertyOpExit());
   523         return reinterpret_cast<IonOOLPropertyOpExitFrameLayout *>(footer());
   524     }
   525     inline IonOOLProxyExitFrameLayout *oolProxyExit() {
   526         JS_ASSERT(isOOLProxyExit());
   527         return reinterpret_cast<IonOOLProxyExitFrameLayout *>(footer());
   528     }
   529     inline IonDOMExitFrameLayout *DOMExit() {
   530         JS_ASSERT(isDomExit());
   531         return reinterpret_cast<IonDOMExitFrameLayout *>(footer());
   532     }
   533 };
   535 // Cannot inherit implementa<tion since we need to extend the top of
   536 // IonExitFrameLayout.
   537 class IonNativeExitFrameLayout
   538 {
   539   protected: // only to silence a clang warning about unused private fields
   540     IonExitFooterFrame footer_;
   541     IonExitFrameLayout exit_;
   542     uintptr_t argc_;
   544     // We need to split the Value into 2 fields of 32 bits, otherwise the C++
   545     // compiler may add some padding between the fields.
   546     uint32_t loCalleeResult_;
   547     uint32_t hiCalleeResult_;
   549   public:
   550     static inline size_t Size() {
   551         return sizeof(IonNativeExitFrameLayout);
   552     }
   554     static size_t offsetOfResult() {
   555         return offsetof(IonNativeExitFrameLayout, loCalleeResult_);
   556     }
   557     inline Value *vp() {
   558         return reinterpret_cast<Value*>(&loCalleeResult_);
   559     }
   560     inline uintptr_t argc() const {
   561         return argc_;
   562     }
   563 };
   565 class IonOOLNativeExitFrameLayout
   566 {
   567   protected: // only to silence a clang warning about unused private fields
   568     IonExitFooterFrame footer_;
   569     IonExitFrameLayout exit_;
   571     // pointer to root the stub's JitCode
   572     JitCode *stubCode_;
   574     uintptr_t argc_;
   576     // We need to split the Value into 2 fields of 32 bits, otherwise the C++
   577     // compiler may add some padding between the fields.
   578     uint32_t loCalleeResult_;
   579     uint32_t hiCalleeResult_;
   581     // Split Value for |this| and args above.
   582     uint32_t loThis_;
   583     uint32_t hiThis_;
   585   public:
   586     static inline size_t Size(size_t argc) {
   587         // The frame accounts for the callee/result and |this|, so we only need args.
   588         return sizeof(IonOOLNativeExitFrameLayout) + (argc * sizeof(Value));
   589     }
   591     static size_t offsetOfResult() {
   592         return offsetof(IonOOLNativeExitFrameLayout, loCalleeResult_);
   593     }
   595     inline JitCode **stubCode() {
   596         return &stubCode_;
   597     }
   598     inline Value *vp() {
   599         return reinterpret_cast<Value*>(&loCalleeResult_);
   600     }
   601     inline Value *thisp() {
   602         return reinterpret_cast<Value*>(&loThis_);
   603     }
   604     inline uintptr_t argc() const {
   605         return argc_;
   606     }
   607 };
   609 class IonOOLPropertyOpExitFrameLayout
   610 {
   611   protected: // only to silence a clang warning about unused private fields
   612     IonExitFooterFrame footer_;
   613     IonExitFrameLayout exit_;
   615     // Object for HandleObject
   616     JSObject *obj_;
   618     // id for HandleId
   619     jsid id_;
   621     // space for MutableHandleValue result
   622     // use two uint32_t so compiler doesn't align.
   623     uint32_t vp0_;
   624     uint32_t vp1_;
   626     // pointer to root the stub's JitCode
   627     JitCode *stubCode_;
   629   public:
   630     static inline size_t Size() {
   631         return sizeof(IonOOLPropertyOpExitFrameLayout);
   632     }
   634     static size_t offsetOfResult() {
   635         return offsetof(IonOOLPropertyOpExitFrameLayout, vp0_);
   636     }
   638     inline JitCode **stubCode() {
   639         return &stubCode_;
   640     }
   641     inline Value *vp() {
   642         return reinterpret_cast<Value*>(&vp0_);
   643     }
   644     inline jsid *id() {
   645         return &id_;
   646     }
   647     inline JSObject **obj() {
   648         return &obj_;
   649     }
   650 };
   652 // Proxy::get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
   653 //            MutableHandleValue vp)
   654 // Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
   655 //            bool strict, MutableHandleValue vp)
   656 class IonOOLProxyExitFrameLayout
   657 {
   658   protected: // only to silence a clang warning about unused private fields
   659     IonExitFooterFrame footer_;
   660     IonExitFrameLayout exit_;
   662     // The proxy object.
   663     JSObject *proxy_;
   665     // Object for HandleObject
   666     JSObject *receiver_;
   668     // id for HandleId
   669     jsid id_;
   671     // space for MutableHandleValue result
   672     // use two uint32_t so compiler doesn't align.
   673     uint32_t vp0_;
   674     uint32_t vp1_;
   676     // pointer to root the stub's JitCode
   677     JitCode *stubCode_;
   679   public:
   680     static inline size_t Size() {
   681         return sizeof(IonOOLProxyExitFrameLayout);
   682     }
   684     static size_t offsetOfResult() {
   685         return offsetof(IonOOLProxyExitFrameLayout, vp0_);
   686     }
   688     inline JitCode **stubCode() {
   689         return &stubCode_;
   690     }
   691     inline Value *vp() {
   692         return reinterpret_cast<Value*>(&vp0_);
   693     }
   694     inline jsid *id() {
   695         return &id_;
   696     }
   697     inline JSObject **receiver() {
   698         return &receiver_;
   699     }
   700     inline JSObject **proxy() {
   701         return &proxy_;
   702     }
   703 };
   705 class IonDOMExitFrameLayout
   706 {
   707   protected: // only to silence a clang warning about unused private fields
   708     IonExitFooterFrame footer_;
   709     IonExitFrameLayout exit_;
   710     JSObject *thisObj;
   712     // We need to split the Value into 2 fields of 32 bits, otherwise the C++
   713     // compiler may add some padding between the fields.
   714     uint32_t loCalleeResult_;
   715     uint32_t hiCalleeResult_;
   717   public:
   718     static inline size_t Size() {
   719         return sizeof(IonDOMExitFrameLayout);
   720     }
   722     static size_t offsetOfResult() {
   723         return offsetof(IonDOMExitFrameLayout, loCalleeResult_);
   724     }
   725     inline Value *vp() {
   726         return reinterpret_cast<Value*>(&loCalleeResult_);
   727     }
   728     inline JSObject **thisObjAddress() {
   729         return &thisObj;
   730     }
   731     inline bool isMethodFrame() {
   732         return footer_.jitCode() == ION_FRAME_DOMMETHOD;
   733     }
   734 };
   736 struct IonDOMMethodExitFrameLayoutTraits;
   738 class IonDOMMethodExitFrameLayout
   739 {
   740   protected: // only to silence a clang warning about unused private fields
   741     IonExitFooterFrame footer_;
   742     IonExitFrameLayout exit_;
   743     // This must be the last thing pushed, so as to stay common with
   744     // IonDOMExitFrameLayout.
   745     JSObject *thisObj_;
   746     Value *argv_;
   747     uintptr_t argc_;
   749     // We need to split the Value into 2 fields of 32 bits, otherwise the C++
   750     // compiler may add some padding between the fields.
   751     uint32_t loCalleeResult_;
   752     uint32_t hiCalleeResult_;
   754     friend struct IonDOMMethodExitFrameLayoutTraits;
   756   public:
   757     static inline size_t Size() {
   758         return sizeof(IonDOMMethodExitFrameLayout);
   759     }
   761     static size_t offsetOfResult() {
   762         return offsetof(IonDOMMethodExitFrameLayout, loCalleeResult_);
   763     }
   765     inline Value *vp() {
   766         // The code in visitCallDOMNative depends on this static assert holding
   767         JS_STATIC_ASSERT(offsetof(IonDOMMethodExitFrameLayout, loCalleeResult_) ==
   768                          (offsetof(IonDOMMethodExitFrameLayout, argc_) + sizeof(uintptr_t)));
   769         return reinterpret_cast<Value*>(&loCalleeResult_);
   770     }
   771     inline JSObject **thisObjAddress() {
   772         return &thisObj_;
   773     }
   774     inline uintptr_t argc() {
   775         return argc_;
   776     }
   777 };
   779 struct IonDOMMethodExitFrameLayoutTraits {
   780     static const size_t offsetOfArgcFromArgv =
   781         offsetof(IonDOMMethodExitFrameLayout, argc_) -
   782         offsetof(IonDOMMethodExitFrameLayout, argv_);
   783 };
   785 class ICStub;
   787 class IonBaselineStubFrameLayout : public IonCommonFrameLayout
   788 {
   789   public:
   790     static inline size_t Size() {
   791         return sizeof(IonBaselineStubFrameLayout);
   792     }
   794     static inline int reverseOffsetOfStubPtr() {
   795         return -int(sizeof(void *));
   796     }
   797     static inline int reverseOffsetOfSavedFramePtr() {
   798         return -int(2 * sizeof(void *));
   799     }
   801     inline ICStub *maybeStubPtr() {
   802         uint8_t *fp = reinterpret_cast<uint8_t *>(this);
   803         return *reinterpret_cast<ICStub **>(fp + reverseOffsetOfStubPtr());
   804     }
   805     inline void setStubPtr(ICStub *stub) {
   806         uint8_t *fp = reinterpret_cast<uint8_t *>(this);
   807         *reinterpret_cast<ICStub **>(fp + reverseOffsetOfStubPtr()) = stub;
   808     }
   809 };
   811 // An invalidation bailout stack is at the stack pointer for the callee frame.
   812 class InvalidationBailoutStack
   813 {
   814     mozilla::Array<double, FloatRegisters::Total> fpregs_;
   815     mozilla::Array<uintptr_t, Registers::Total> regs_;
   816     IonScript   *ionScript_;
   817     uint8_t       *osiPointReturnAddress_;
   819   public:
   820     uint8_t *sp() const {
   821         return (uint8_t *) this + sizeof(InvalidationBailoutStack);
   822     }
   823     IonJSFrameLayout *fp() const;
   824     MachineState machine() {
   825         return MachineState::FromBailout(regs_, fpregs_);
   826     }
   828     IonScript *ionScript() const {
   829         return ionScript_;
   830     }
   831     uint8_t *osiPointReturnAddress() const {
   832         return osiPointReturnAddress_;
   833     }
   835     void checkInvariants() const;
   836 };
   838 void
   839 GetPcScript(JSContext *cx, JSScript **scriptRes, jsbytecode **pcRes);
   841 CalleeToken
   842 MarkCalleeToken(JSTracer *trc, CalleeToken token);
   844 } /* namespace jit */
   845 } /* namespace js */
   847 #endif // JS_ION
   849 #endif /* jit_IonFrames_h */

mercurial