Home | History | Annotate | Download | only in jit
      1 /*
      2  * Copyright (C) 2008 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  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #ifndef JITStubs_h
     30 #define JITStubs_h
     31 
     32 #include <wtf/Platform.h>
     33 
     34 #include "MacroAssemblerCodeRef.h"
     35 #include "Register.h"
     36 
     37 #if ENABLE(JIT)
     38 
     39 namespace JSC {
     40 
     41     struct StructureStubInfo;
     42 
     43     class CodeBlock;
     44     class ExecutablePool;
     45     class FunctionExecutable;
     46     class Identifier;
     47     class JSGlobalData;
     48     class JSGlobalData;
     49     class JSObject;
     50     class JSPropertyNameIterator;
     51     class JSValue;
     52     class JSValueEncodedAsPointer;
     53     class Profiler;
     54     class PropertySlot;
     55     class PutPropertySlot;
     56     class RegisterFile;
     57     class JSGlobalObject;
     58     class RegExp;
     59 
     60     union JITStubArg {
     61         void* asPointer;
     62         EncodedJSValue asEncodedJSValue;
     63         int32_t asInt32;
     64 
     65         JSValue jsValue() { return JSValue::decode(asEncodedJSValue); }
     66         JSObject* jsObject() { return static_cast<JSObject*>(asPointer); }
     67         Identifier& identifier() { return *static_cast<Identifier*>(asPointer); }
     68         int32_t int32() { return asInt32; }
     69         CodeBlock* codeBlock() { return static_cast<CodeBlock*>(asPointer); }
     70         FunctionExecutable* function() { return static_cast<FunctionExecutable*>(asPointer); }
     71         RegExp* regExp() { return static_cast<RegExp*>(asPointer); }
     72         JSPropertyNameIterator* propertyNameIterator() { return static_cast<JSPropertyNameIterator*>(asPointer); }
     73         JSGlobalObject* globalObject() { return static_cast<JSGlobalObject*>(asPointer); }
     74         JSString* jsString() { return static_cast<JSString*>(asPointer); }
     75         ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); }
     76     };
     77 
     78     struct TrampolineStructure {
     79         MacroAssemblerCodePtr ctiStringLengthTrampoline;
     80         MacroAssemblerCodePtr ctiVirtualCallLink;
     81         MacroAssemblerCodePtr ctiVirtualCall;
     82         MacroAssemblerCodePtr ctiNativeCallThunk;
     83         MacroAssemblerCodePtr ctiSoftModulo;
     84     };
     85 
     86 #if CPU(X86_64)
     87     struct JITStackFrame {
     88         void* reserved; // Unused
     89         JITStubArg args[6];
     90         void* padding[2]; // Maintain 32-byte stack alignment (possibly overkill).
     91 
     92         void* code;
     93         RegisterFile* registerFile;
     94         CallFrame* callFrame;
     95         JSValue* exception;
     96         Profiler** enabledProfilerReference;
     97         JSGlobalData* globalData;
     98 
     99         void* savedRBX;
    100         void* savedR15;
    101         void* savedR14;
    102         void* savedR13;
    103         void* savedR12;
    104         void* savedRBP;
    105         void* savedRIP;
    106 
    107         // When JIT code makes a call, it pushes its return address just below the rest of the stack.
    108         ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; }
    109     };
    110 #elif CPU(X86)
    111 #if COMPILER(MSVC)
    112 #pragma pack(push)
    113 #pragma pack(4)
    114 #endif // COMPILER(MSVC)
    115     struct JITStackFrame {
    116         void* reserved; // Unused
    117         JITStubArg args[6];
    118 #if USE(JSVALUE32_64)
    119         void* padding[2]; // Maintain 16-byte stack alignment.
    120 #endif
    121 
    122         void* savedEBX;
    123         void* savedEDI;
    124         void* savedESI;
    125         void* savedEBP;
    126         void* savedEIP;
    127 
    128         void* code;
    129         RegisterFile* registerFile;
    130         CallFrame* callFrame;
    131         JSValue* exception;
    132         Profiler** enabledProfilerReference;
    133         JSGlobalData* globalData;
    134 
    135         // When JIT code makes a call, it pushes its return address just below the rest of the stack.
    136         ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; }
    137     };
    138 #if COMPILER(MSVC)
    139 #pragma pack(pop)
    140 #endif // COMPILER(MSVC)
    141 #elif CPU(ARM_THUMB2)
    142     struct JITStackFrame {
    143         void* reserved; // Unused
    144         JITStubArg args[6];
    145 #if USE(JSVALUE32_64)
    146         void* padding[2]; // Maintain 16-byte stack alignment.
    147 #endif
    148 
    149         ReturnAddressPtr thunkReturnAddress;
    150 
    151         void* preservedReturnAddress;
    152         void* preservedR4;
    153         void* preservedR5;
    154         void* preservedR6;
    155 
    156         // These arguments passed in r1..r3 (r0 contained the entry code pointed, which is not preserved)
    157         RegisterFile* registerFile;
    158         CallFrame* callFrame;
    159         JSValue* exception;
    160 
    161         void* padding2;
    162 
    163         // These arguments passed on the stack.
    164         Profiler** enabledProfilerReference;
    165         JSGlobalData* globalData;
    166 
    167         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
    168     };
    169 #elif CPU(ARM_TRADITIONAL)
    170     struct JITStackFrame {
    171         JITStubArg padding; // Unused
    172         JITStubArg args[7];
    173 
    174         ReturnAddressPtr thunkReturnAddress;
    175 
    176         void* preservedR4;
    177         void* preservedR5;
    178         void* preservedR6;
    179         void* preservedR7;
    180         void* preservedR8;
    181         void* preservedLink;
    182 
    183         RegisterFile* registerFile;
    184         CallFrame* callFrame;
    185         JSValue* exception;
    186 
    187         // These arguments passed on the stack.
    188         Profiler** enabledProfilerReference;
    189         JSGlobalData* globalData;
    190 
    191         // When JIT code makes a call, it pushes its return address just below the rest of the stack.
    192         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
    193     };
    194 #else
    195 #error "JITStackFrame not defined for this platform."
    196 #endif
    197 
    198 #define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*))
    199 
    200 #if USE(JIT_STUB_ARGUMENT_VA_LIST)
    201     #define STUB_ARGS_DECLARATION void* args, ...
    202     #define STUB_ARGS (reinterpret_cast<void**>(vl_args) - 1)
    203 
    204     #if COMPILER(MSVC)
    205     #define JIT_STUB __cdecl
    206     #else
    207     #define JIT_STUB
    208     #endif
    209 #else
    210     #define STUB_ARGS_DECLARATION void** args
    211     #define STUB_ARGS (args)
    212 
    213     #if CPU(X86) && COMPILER(MSVC)
    214     #define JIT_STUB __fastcall
    215     #elif CPU(X86) && COMPILER(GCC)
    216     #define JIT_STUB  __attribute__ ((fastcall))
    217     #else
    218     #define JIT_STUB
    219     #endif
    220 #endif
    221 
    222 #if CPU(X86_64)
    223     struct VoidPtrPair {
    224         void* first;
    225         void* second;
    226     };
    227     #define RETURN_POINTER_PAIR(a,b) VoidPtrPair pair = { a, b }; return pair
    228 #else
    229     // MSVC doesn't support returning a two-value struct in two registers, so
    230     // we cast the struct to int64_t instead.
    231     typedef uint64_t VoidPtrPair;
    232     union VoidPtrPairUnion {
    233         struct { void* first; void* second; } s;
    234         VoidPtrPair i;
    235     };
    236     #define RETURN_POINTER_PAIR(a,b) VoidPtrPairUnion pair = {{ a, b }}; return pair.i
    237 #endif
    238 
    239     extern "C" void ctiVMThrowTrampoline();
    240     extern "C" void ctiOpThrowNotCaught();
    241     extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue* exception, Profiler**, JSGlobalData*);
    242 
    243     class JITThunks {
    244     public:
    245         JITThunks(JSGlobalData*);
    246 
    247         static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&, StructureStubInfo* stubInfo);
    248         static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo);
    249 
    250         MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; }
    251         MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; }
    252         MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; }
    253         MacroAssemblerCodePtr ctiNativeCallThunk() { return m_trampolineStructure.ctiNativeCallThunk; }
    254         MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; }
    255 
    256     private:
    257         RefPtr<ExecutablePool> m_executablePool;
    258 
    259         TrampolineStructure m_trampolineStructure;
    260     };
    261 
    262 extern "C" {
    263     EncodedJSValue JIT_STUB cti_op_add(STUB_ARGS_DECLARATION);
    264     EncodedJSValue JIT_STUB cti_op_bitand(STUB_ARGS_DECLARATION);
    265     EncodedJSValue JIT_STUB cti_op_bitnot(STUB_ARGS_DECLARATION);
    266     EncodedJSValue JIT_STUB cti_op_bitor(STUB_ARGS_DECLARATION);
    267     EncodedJSValue JIT_STUB cti_op_bitxor(STUB_ARGS_DECLARATION);
    268     EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION);
    269     EncodedJSValue JIT_STUB cti_op_call_eval(STUB_ARGS_DECLARATION);
    270     EncodedJSValue JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION);
    271     EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION);
    272     EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION);
    273     EncodedJSValue JIT_STUB cti_op_del_by_val(STUB_ARGS_DECLARATION);
    274     EncodedJSValue JIT_STUB cti_op_div(STUB_ARGS_DECLARATION);
    275     EncodedJSValue JIT_STUB cti_op_get_by_id(STUB_ARGS_DECLARATION);
    276     EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION);
    277     EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION);
    278     EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION);
    279     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION);
    280     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION);
    281     EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION);
    282     EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION);
    283     EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION);
    284     EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION);
    285     EncodedJSValue JIT_STUB cti_op_get_by_val_byte_array(STUB_ARGS_DECLARATION);
    286     EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION);
    287     EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION);
    288     EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION);
    289     EncodedJSValue JIT_STUB cti_op_is_boolean(STUB_ARGS_DECLARATION);
    290     EncodedJSValue JIT_STUB cti_op_is_function(STUB_ARGS_DECLARATION);
    291     EncodedJSValue JIT_STUB cti_op_is_number(STUB_ARGS_DECLARATION);
    292     EncodedJSValue JIT_STUB cti_op_is_object(STUB_ARGS_DECLARATION);
    293     EncodedJSValue JIT_STUB cti_op_is_string(STUB_ARGS_DECLARATION);
    294     EncodedJSValue JIT_STUB cti_op_is_undefined(STUB_ARGS_DECLARATION);
    295     EncodedJSValue JIT_STUB cti_op_less(STUB_ARGS_DECLARATION);
    296     EncodedJSValue JIT_STUB cti_op_lesseq(STUB_ARGS_DECLARATION);
    297     EncodedJSValue JIT_STUB cti_op_lshift(STUB_ARGS_DECLARATION);
    298     EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION);
    299     EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION);
    300     EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION);
    301     EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION);
    302     EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION);
    303     EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION);
    304     EncodedJSValue JIT_STUB cti_op_post_inc(STUB_ARGS_DECLARATION);
    305     EncodedJSValue JIT_STUB cti_op_pre_dec(STUB_ARGS_DECLARATION);
    306     EncodedJSValue JIT_STUB cti_op_pre_inc(STUB_ARGS_DECLARATION);
    307     EncodedJSValue JIT_STUB cti_op_resolve(STUB_ARGS_DECLARATION);
    308     EncodedJSValue JIT_STUB cti_op_resolve_base(STUB_ARGS_DECLARATION);
    309     EncodedJSValue JIT_STUB cti_op_resolve_global(STUB_ARGS_DECLARATION);
    310     EncodedJSValue JIT_STUB cti_op_resolve_skip(STUB_ARGS_DECLARATION);
    311     EncodedJSValue JIT_STUB cti_op_resolve_with_base(STUB_ARGS_DECLARATION);
    312     EncodedJSValue JIT_STUB cti_op_rshift(STUB_ARGS_DECLARATION);
    313     EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION);
    314     EncodedJSValue JIT_STUB cti_op_stricteq(STUB_ARGS_DECLARATION);
    315     EncodedJSValue JIT_STUB cti_op_sub(STUB_ARGS_DECLARATION);
    316     EncodedJSValue JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION);
    317     EncodedJSValue JIT_STUB cti_op_to_jsnumber(STUB_ARGS_DECLARATION);
    318     EncodedJSValue JIT_STUB cti_op_to_primitive(STUB_ARGS_DECLARATION);
    319     EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION);
    320     EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION);
    321     EncodedJSValue JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION);
    322     EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION);
    323     JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS_DECLARATION);
    324     JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION);
    325     JSObject* JIT_STUB cti_op_new_error(STUB_ARGS_DECLARATION);
    326     JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION);
    327     JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS_DECLARATION);
    328     JSObject* JIT_STUB cti_op_new_object(STUB_ARGS_DECLARATION);
    329     JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS_DECLARATION);
    330     JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS_DECLARATION);
    331     JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS_DECLARATION);
    332     JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS_DECLARATION);
    333     JSObject* JIT_STUB cti_op_put_by_id_transition_realloc(STUB_ARGS_DECLARATION);
    334     JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS_DECLARATION);
    335     VoidPtrPair JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION);
    336     int JIT_STUB cti_op_eq(STUB_ARGS_DECLARATION);
    337 #if USE(JSVALUE32_64)
    338     int JIT_STUB cti_op_eq_strings(STUB_ARGS_DECLARATION);
    339 #endif
    340     int JIT_STUB cti_op_jless(STUB_ARGS_DECLARATION);
    341     int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION);
    342     int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION);
    343     int JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION);
    344     int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION);
    345     int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION);
    346     int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION);
    347     void JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION);
    348     void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION);
    349     void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION);
    350     void JIT_STUB cti_op_end(STUB_ARGS_DECLARATION);
    351     void JIT_STUB cti_op_jmp_scopes(STUB_ARGS_DECLARATION);
    352     void JIT_STUB cti_op_pop_scope(STUB_ARGS_DECLARATION);
    353     void JIT_STUB cti_op_profile_did_call(STUB_ARGS_DECLARATION);
    354     void JIT_STUB cti_op_profile_will_call(STUB_ARGS_DECLARATION);
    355     void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION);
    356     void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION);
    357     void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION);
    358     void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION);
    359     void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION);
    360     void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION);
    361     void JIT_STUB cti_op_put_getter(STUB_ARGS_DECLARATION);
    362     void JIT_STUB cti_op_put_setter(STUB_ARGS_DECLARATION);
    363     void JIT_STUB cti_op_ret_scopeChain(STUB_ARGS_DECLARATION);
    364     void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION);
    365     void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION);
    366     void JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION);
    367     void* JIT_STUB cti_op_call_JSFunction(STUB_ARGS_DECLARATION);
    368     void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION);
    369     void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION);
    370     void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION);
    371     void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION);
    372 } // extern "C"
    373 
    374 } // namespace JSC
    375 
    376 #endif // ENABLE(JIT)
    377 
    378 #endif // JITStubs_h
    379