Home | History | Annotate | Download | only in jit
      1 /*
      2  * Copyright (C) 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef SpecializedThunkJIT_h
     27 #define SpecializedThunkJIT_h
     28 
     29 #if ENABLE(JIT)
     30 
     31 #include "Executable.h"
     32 #include "JSInterfaceJIT.h"
     33 #include "LinkBuffer.h"
     34 
     35 namespace JSC {
     36 
     37     class SpecializedThunkJIT : public JSInterfaceJIT {
     38     public:
     39         static const int ThisArgument = -1;
     40         SpecializedThunkJIT(int expectedArgCount, JSGlobalData* globalData, ExecutablePool* pool)
     41             : m_expectedArgCount(expectedArgCount)
     42             , m_globalData(globalData)
     43             , m_pool(pool)
     44         {
     45             // Check that we have the expected number of arguments
     46             m_failures.append(branch32(NotEqual, Address(callFrameRegister, RegisterFile::ArgumentCount * (int)sizeof(Register)), TrustedImm32(expectedArgCount + 1)));
     47         }
     48 
     49         void loadDoubleArgument(int argument, FPRegisterID dst, RegisterID scratch)
     50         {
     51             unsigned src = argumentToVirtualRegister(argument);
     52             m_failures.append(emitLoadDouble(src, dst, scratch));
     53         }
     54 
     55         void loadCellArgument(int argument, RegisterID dst)
     56         {
     57             unsigned src = argumentToVirtualRegister(argument);
     58             m_failures.append(emitLoadJSCell(src, dst));
     59         }
     60 
     61         void loadJSStringArgument(int argument, RegisterID dst)
     62         {
     63             loadCellArgument(argument, dst);
     64             m_failures.append(branchPtr(NotEqual, Address(dst, 0), TrustedImmPtr(m_globalData->jsStringVPtr)));
     65             m_failures.append(branchTest32(NonZero, Address(dst, OBJECT_OFFSETOF(JSString, m_fiberCount))));
     66         }
     67 
     68         void loadInt32Argument(int argument, RegisterID dst, Jump& failTarget)
     69         {
     70             unsigned src = argumentToVirtualRegister(argument);
     71             failTarget = emitLoadInt32(src, dst);
     72         }
     73 
     74         void loadInt32Argument(int argument, RegisterID dst)
     75         {
     76             Jump conversionFailed;
     77             loadInt32Argument(argument, dst, conversionFailed);
     78             m_failures.append(conversionFailed);
     79         }
     80 
     81         void appendFailure(const Jump& failure)
     82         {
     83             m_failures.append(failure);
     84         }
     85 
     86         void returnJSValue(RegisterID src)
     87         {
     88             if (src != regT0)
     89                 move(src, regT0);
     90             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
     91             ret();
     92         }
     93 
     94         void returnDouble(FPRegisterID src)
     95         {
     96 #if USE(JSVALUE64)
     97             moveDoubleToPtr(src, regT0);
     98             subPtr(tagTypeNumberRegister, regT0);
     99 #else
    100             storeDouble(src, Address(stackPointerRegister, -(int)sizeof(double)));
    101             loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.tag) - sizeof(double)), regT1);
    102             loadPtr(Address(stackPointerRegister, OBJECT_OFFSETOF(JSValue, u.asBits.payload) - sizeof(double)), regT0);
    103 #endif
    104             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
    105             ret();
    106         }
    107 
    108         void returnInt32(RegisterID src)
    109         {
    110             if (src != regT0)
    111                 move(src, regT0);
    112             tagReturnAsInt32();
    113             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
    114             ret();
    115         }
    116 
    117         void returnJSCell(RegisterID src)
    118         {
    119             if (src != regT0)
    120                 move(src, regT0);
    121             tagReturnAsJSCell();
    122             loadPtr(payloadFor(RegisterFile::CallerFrame, callFrameRegister), callFrameRegister);
    123             ret();
    124         }
    125 
    126         MacroAssemblerCodePtr finalize(MacroAssemblerCodePtr fallback)
    127         {
    128             LinkBuffer patchBuffer(this, m_pool.get(), 0);
    129             patchBuffer.link(m_failures, CodeLocationLabel(fallback));
    130             return patchBuffer.finalizeCode().m_code;
    131         }
    132 
    133     private:
    134         int argumentToVirtualRegister(unsigned argument)
    135         {
    136             return -static_cast<int>(RegisterFile::CallFrameHeaderSize + (m_expectedArgCount - argument));
    137         }
    138 
    139         void tagReturnAsInt32()
    140         {
    141 #if USE(JSVALUE64)
    142             orPtr(tagTypeNumberRegister, regT0);
    143 #else
    144             move(TrustedImm32(JSValue::Int32Tag), regT1);
    145 #endif
    146         }
    147 
    148         void tagReturnAsJSCell()
    149         {
    150 #if USE(JSVALUE32_64)
    151             move(TrustedImm32(JSValue::CellTag), regT1);
    152 #endif
    153         }
    154 
    155         int m_expectedArgCount;
    156         JSGlobalData* m_globalData;
    157         RefPtr<ExecutablePool> m_pool;
    158         MacroAssembler::JumpList m_failures;
    159     };
    160 
    161 }
    162 
    163 #endif // ENABLE(JIT)
    164 
    165 #endif // SpecializedThunkJIT_h
    166