Changeset 44514 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Jun 8, 2009, 6:40:59 PM (16 years ago)
Author:
[email protected]
Message:

2009-06-08 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

Add (incomplete) support to YARR for running with the jit enabled
on Arm thumb2 platforms. Adds new Assembler/MacroAssembler classes,
along with cache flushing support, tweaks to MacroAssemblerCodePtr
to support decorated thumb code pointers, and new enter/exit code
to YARR jit for the platform.

Support for this platform is still under development - the assembler
currrently only supports planting and linking jumps with a 16Mb range.
As such, initially commiting in a disabled state.

Add new assembler files.

  • assembler/ARMv7Assembler.h: Added.

Add new Assembler.

  • assembler/AbstractMacroAssembler.h:

Tweaks to ensure sizes of pointer values planted in JIT code do not change.

  • assembler/MacroAssembler.h:

On ARMv7 platforms use MacroAssemblerARMv7.

  • assembler/MacroAssemblerARMv7.h: Added.

Add new MacroAssembler.

  • assembler/MacroAssemblerCodeRef.h: (JSC::FunctionPtr::FunctionPtr):

Add better ASSERT.

(JSC::ReturnAddressPtr::ReturnAddressPtr):

Add better ASSERT.

(JSC::MacroAssemblerCodePtr::MacroAssemblerCodePtr):

On ARMv7, MacroAssemblerCodePtr's mush be 'decorated' with a low bit set,
to indicate to the processor that the code is thumb code, not traditional
32-bit ARM.

(JSC::MacroAssemblerCodePtr::dataLocation):

On ARMv7, decoration must be removed.

  • jit/ExecutableAllocator.h: (JSC::ExecutableAllocator::makeWritable):

Reformatted, no change.

(JSC::ExecutableAllocator::makeExecutable):

When marking code executable also cache flush it, where necessary.

(JSC::ExecutableAllocator::MakeWritable::MakeWritable):

Only use the null implementation of this class if both !ASSEMBLER_WX_EXCLUSIVE
and running on x86(_64) - on other platforms we may also need ensure that
makeExecutable is called at the end to flush caches.

(JSC::ExecutableAllocator::reprotectRegion):

Reformatted, no change.

(JSC::ExecutableAllocator::cacheFlush):

Cache flush a region of memory, or platforms where this is necessary.

  • wtf/Platform.h:

Add changes necessary to allow YARR jit to build on this platform, disabled.

  • yarr/RegexJIT.cpp: (JSC::Yarr::RegexGenerator::generateEnter): (JSC::Yarr::RegexGenerator::generateReturn):

Add support to these methods for ARMv7.

Location:
trunk/JavaScriptCore
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r44513 r44514  
     12009-06-08  Gavin Barraclough  <[email protected]>
     2
     3        Reviewed by Geoff Garen.
     4
     5        Add (incomplete) support to YARR for running with the jit enabled
     6        on Arm thumb2 platforms.  Adds new Assembler/MacroAssembler classes,
     7        along with cache flushing support, tweaks to MacroAssemblerCodePtr
     8        to support decorated thumb code pointers, and new enter/exit code
     9        to YARR jit for the platform.
     10
     11        Support for this platform is still under development - the assembler
     12        currrently only supports planting and linking jumps with a 16Mb range.
     13        As such, initially commiting in a disabled state.
     14
     15        * JavaScriptCore.xcodeproj/project.pbxproj:
     16            Add new assembler files.
     17        * assembler/ARMv7Assembler.h: Added.
     18            Add new Assembler.
     19        * assembler/AbstractMacroAssembler.h:
     20            Tweaks to ensure sizes of pointer values planted in JIT code do not change.
     21        * assembler/MacroAssembler.h:
     22            On ARMv7 platforms use MacroAssemblerARMv7.
     23        * assembler/MacroAssemblerARMv7.h: Added.
     24            Add new MacroAssembler.
     25        * assembler/MacroAssemblerCodeRef.h:
     26        (JSC::FunctionPtr::FunctionPtr):
     27            Add better ASSERT.
     28        (JSC::ReturnAddressPtr::ReturnAddressPtr):
     29            Add better ASSERT.
     30        (JSC::MacroAssemblerCodePtr::MacroAssemblerCodePtr):
     31            On ARMv7, MacroAssemblerCodePtr's mush be 'decorated' with a low bit set,
     32            to indicate to the processor that the code is thumb code, not traditional
     33            32-bit ARM.
     34        (JSC::MacroAssemblerCodePtr::dataLocation):
     35            On ARMv7, decoration must be removed.
     36        * jit/ExecutableAllocator.h:
     37        (JSC::ExecutableAllocator::makeWritable):
     38            Reformatted, no change.
     39        (JSC::ExecutableAllocator::makeExecutable):
     40            When marking code executable also cache flush it, where necessary.
     41        (JSC::ExecutableAllocator::MakeWritable::MakeWritable):
     42            Only use the null implementation of this class if both !ASSEMBLER_WX_EXCLUSIVE
     43            and running on x86(_64) - on other platforms we may also need ensure that
     44            makeExecutable is called at the end to flush caches.
     45        (JSC::ExecutableAllocator::reprotectRegion):
     46            Reformatted, no change.
     47        (JSC::ExecutableAllocator::cacheFlush):
     48            Cache flush a region of memory, or platforms where this is necessary.
     49        * wtf/Platform.h:
     50            Add changes necessary to allow YARR jit to build on this platform, disabled.
     51        * yarr/RegexJIT.cpp:
     52        (JSC::Yarr::RegexGenerator::generateEnter):
     53        (JSC::Yarr::RegexGenerator::generateReturn):
     54            Add support to these methods for ARMv7.
     55
    1562009-06-08  Dimitri Glazkov  <[email protected]>
    257
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r44508 r44514  
    129129                869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC /* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; };
    130130                86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */; };
     131                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; };
     132                86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; };
    131133                86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; };
    132134                86CC85A10EE79A4700288682 /* JITInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CC85A00EE79A4700288682 /* JITInlineMethods.h */; };
     
    628630                869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultType.h; sourceTree = "<group>"; };
    629631                86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic.cpp; sourceTree = "<group>"; };
     632                86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; };
     633                86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARMv7.h; sourceTree = "<group>"; };
    630634                86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssembler.h; sourceTree = "<group>"; };
    631635                86CC85A00EE79A4700288682 /* JITInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITInlineMethods.h; sourceTree = "<group>"; };
     
    15321536                        children = (
    15331537                                860161DF0F3A83C100F84710 /* AbstractMacroAssembler.h */,
     1538                                86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */,
    15341539                                9688CB130ED12B4E001D649F /* AssemblerBuffer.h */,
    15351540                                863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */,
     1541                                86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */,
    15361542                                860161E00F3A83C100F84710 /* MacroAssemblerX86.h */,
    15371543                                860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */,
     
    18411847                                0BDFFAE00FC6192900D69EF4 /* CrossThreadRefCounted.h in Headers */,
    18421848                                0BDFFAE10FC6193100D69EF4 /* OwnFastMallocPtr.h in Headers */,
     1849                                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
     1850                                86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */,
    18431851                        );
    18441852                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r44476 r44514  
    182182        explicit Imm32(int32_t value)
    183183            : m_value(value)
     184#if PLATFORM(ARM_V7)
     185            , m_isPointer(false)
     186#endif
    184187        {
    185188        }
     
    188191        explicit Imm32(ImmPtr ptr)
    189192            : m_value(ptr.asIntptr())
    190         {
    191         }
     193#if PLATFORM(ARM_V7)
     194            , m_isPointer(true)
    192195#endif
     196        {
     197        }
     198#endif
    193199
    194200        int32_t m_value;
     201#if PLATFORM(ARM_V7)
     202        // We rely on being able to regenerate code to recover exception handling
     203        // information.  Since ARMv7 supports 16-bit immediates there is a danger
     204        // that if pointer values change the layout of the generated code will change.
     205        // To avoid this problem, always generate pointers (and thus Imm32s constructed
     206        // from ImmPtrs) with a code sequence that is able  to represent  any pointer
     207        // value - don't use a more compact form in these cases.
     208        bool m_isPointer;
     209#endif
    195210    };
    196211
     
    529544        void relink(CodeLocationLabel destination)
    530545        {
    531             AssemblerType::relinkJump(this->dataLocation(), destination.executableAddress());
     546            AssemblerType::relinkJump(this->dataLocation(), destination.dataLocation());
    532547        }
    533548
     
    787802        void link(Jump jump, CodeLocationLabel label)
    788803        {
    789             AssemblerType::linkJump(code(), jump.m_jmp, label.executableAddress());
     804            AssemblerType::linkJump(code(), jump.m_jmp, label.dataLocation());
    790805        }
    791806
     
    793808        {
    794809            for (unsigned i = 0; i < list.m_jumps.size(); ++i)
    795                 AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, label.executableAddress());
     810                AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, label.dataLocation());
    796811        }
    797812
  • trunk/JavaScriptCore/assembler/MacroAssembler.h

    r43432 r44514  
    3131#if ENABLE(ASSEMBLER)
    3232
    33 #if PLATFORM(X86)
     33#if PLATFORM(ARM_V7)
     34#include "MacroAssemblerARMv7.h"
     35namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; };
     36
     37#elif PLATFORM(X86)
    3438#include "MacroAssemblerX86.h"
    3539namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; };
  • trunk/JavaScriptCore/assembler/MacroAssemblerCodeRef.h

    r44455 r44514  
    3636#if ENABLE(ASSEMBLER)
    3737
     38// ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid
     39// instruction address on the platform (for example, check any alignment requirements).
     40#if PLATFORM(ARM_V7)
     41// ARM/thumb instructions must be 16-bit aligned, but all code pointers to be loaded
     42// into the processor are decorated with the bottom bit set, indicating that this is
     43// thumb code (as oposed to 32-bit traditional ARM).  The first test checks for both
     44// decorated and undectorated null, and the second test ensures that the pointer is
     45// decorated.
     46#define ASSERT_VALID_CODE_POINTER(ptr) \
     47    ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1); \
     48    ASSERT(reinterpret_cast<intptr_t>(ptr) & 1)
     49#else
     50#define ASSERT_VALID_CODE_POINTER(ptr) \
     51    ASSERT(ptr)
     52#endif
     53
    3854namespace JSC {
    3955
     
    5369        : m_value(reinterpret_cast<void*>(value))
    5470    {
    55         ASSERT(m_value);
     71        ASSERT_VALID_CODE_POINTER(m_value);
    5672    }
    5773
     
    8096        : m_value(value)
    8197    {
    82         ASSERT(m_value);
     98        ASSERT_VALID_CODE_POINTER(m_value);
    8399    }
    84100
     
    100116
    101117    explicit MacroAssemblerCodePtr(void* value)
     118#if PLATFORM(ARM_V7)
     119        // Decorate the pointer as a thumb code pointer.
     120        : m_value(reinterpret_cast<char*>(value) + 1)
     121#else
    102122        : m_value(value)
     123#endif
    103124    {
    104         ASSERT(m_value);
     125        ASSERT_VALID_CODE_POINTER(m_value);
    105126    }
    106127
     
    108129        : m_value(ra.value())
    109130    {
    110         ASSERT(m_value);
     131        ASSERT_VALID_CODE_POINTER(m_value);
    111132    }
    112133
    113134    void* executableAddress() const { return m_value; }
    114     void* dataLocation() const { ASSERT(m_value); return m_value; }
     135#if PLATFORM(ARM_V7)
     136    // To use this pointer as a data address remove the decoration.
     137    void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; }
     138#else
     139    void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; }
     140#endif
    115141
    116142private:
  • trunk/JavaScriptCore/jit/ExecutableAllocator.h

    r44341 r44514  
    2727#define ExecutableAllocator_h
    2828
     29#include <limits>
    2930#include <wtf/Assertions.h>
    3031#include <wtf/PassRefPtr.h>
    3132#include <wtf/RefCounted.h>
     33#include <wtf/UnusedParam.h>
    3234#include <wtf/Vector.h>
    3335
    34 #include <limits>
     36#if PLATFORM(IPHONE)
     37#include <libkern/OSCacheControl.h>
     38#include <sys/mman.h>
     39#endif
    3540
    3641#define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize)
     
    152157    }
    153158
    154 #if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
    155     static void makeWritable(void* start, size_t size) { reprotectRegion(start, size, Writable); }
    156     static void makeExecutable(void* start, size_t size) { reprotectRegion(start, size, Executable); }
    157 
     159    static void makeWritable(void* start, size_t size)
     160    {
     161        reprotectRegion(start, size, Writable);
     162    }
     163
     164    static void makeExecutable(void* start, size_t size)
     165    {
     166        reprotectRegion(start, size, Executable);
     167        cacheFlush(start, size);
     168    }
     169
     170#if !ENABLE(ASSEMBLER_WX_EXCLUSIVE) && (PLATFORM(X86) || PLATFORM(X86_64))
     171    // If ASSEMBLER_WX_EXCLUSIVE protection is turned off, and if we're running
     172    // on x86, then MakeWritable has nothing to do.  On non-x86 platforms we need
     173    // to track start & size so we can cache-flush at the end.
     174    class MakeWritable { public: MakeWritable(void*, size_t) {} };
     175#else
    158176    class MakeWritable {
    159177    public:
     
    174192        size_t m_size;
    175193    };
    176 #else
    177     static void makeWritable(void*, size_t) {}
    178     static void makeExecutable(void*, size_t) {}
    179     class MakeWritable { public: MakeWritable(void*, size_t) {} };
    180194#endif
    181195
     
    184198#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
    185199    static void reprotectRegion(void*, size_t, ProtectionSeting);
    186 #endif
     200#else
     201    static void reprotectRegion(void*, size_t, ProtectionSeting) {}
     202#endif
     203
     204   static void cacheFlush(void* code, size_t size)
     205    {
     206#if PLATFORM(X86) || PLATFORM(X86_64)
     207        UNUSED_PARAM(code);
     208        UNUSED_PARAM(size);
     209#elif PLATFORM(ARM_V7) && PLATFORM(IPHONE)
     210        sys_dcache_flush(code, size);
     211        sys_icache_invalidate(code, size);
     212#else
     213#error "ExecutableAllocator::cacheFlush not implemented on this platform."
     214#endif
     215    }
    187216
    188217    RefPtr<ExecutablePool> m_smallAllocationPool;
  • trunk/JavaScriptCore/wtf/Platform.h

    r44511 r44514  
    229229#endif
    230230#endif
     231#if defined(__ARM_ARCH_7A__)
     232#define WTF_PLATFORM_ARM_V7 1
     233#endif
    231234
    232235/* PLATFORM(X86) */
     
    556559#if (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(MAC)) \
    557560 || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86_64) && PLATFORM(MAC)) \
     561 /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ \
     562 || (!defined(ENABLE_YARR_JIT) && PLATFORM(ARM_V7) && PLATFORM(IPHONE) && 0) \
    558563 || (!defined(ENABLE_YARR_JIT) && PLATFORM(X86) && PLATFORM(WIN))
    559564#define ENABLE_YARR 1
     
    570575/* Setting this flag prevents the assembler from using RWX memory; this may improve
    571576   security but currectly comes at a significant performance cost. */
     577#if PLATFORM(ARM_V7) && PLATFORM(IPHONE)
     578#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 1
     579#else
    572580#define ENABLE_ASSEMBLER_WX_EXCLUSIVE 0
     581#endif
    573582
    574583#if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS)
  • trunk/JavaScriptCore/yarr/RegexJIT.cpp

    r44477 r44514  
    4444    friend void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline);
    4545
     46#if PLATFORM(ARM_V7)
     47    static const RegisterID input = ARM::r0;
     48    static const RegisterID index = ARM::r1;
     49    static const RegisterID length = ARM::r2;
     50
     51    static const RegisterID output = ARM::r4;
     52    static const RegisterID regT0 = ARM::r5;
     53    static const RegisterID regT1 = ARM::r6;
     54
     55    static const RegisterID returnRegister = ARM::r0;
     56#endif
    4657#if PLATFORM(X86)
    4758    static const RegisterID input = X86::eax;
     
    12791290    void generateEnter()
    12801291    {
    1281         // On x86 edi & esi are callee preserved registers.
     1292#if PLATFORM(X86_64)
    12821293        push(X86::ebp);
    12831294        move(stackPointerRegister, X86::ebp);
    1284 #if PLATFORM(X86)
     1295#elif PLATFORM(X86)
     1296        push(X86::ebp);
     1297        move(stackPointerRegister, X86::ebp);
    12851298        // TODO: do we need spill registers to fill the output pointer if there are no sub captures?
    12861299        push(X86::ebx);
     
    12881301        push(X86::esi);
    12891302        // load output into edi (2 = saved ebp + return address).
    1290 #if COMPILER(MSVC)
     1303    #if COMPILER(MSVC)
    12911304        loadPtr(Address(X86::ebp, 2 * sizeof(void*)), input);
    12921305        loadPtr(Address(X86::ebp, 3 * sizeof(void*)), index);
    12931306        loadPtr(Address(X86::ebp, 4 * sizeof(void*)), length);
    12941307        loadPtr(Address(X86::ebp, 5 * sizeof(void*)), output);
    1295 #else
     1308    #else
    12961309        loadPtr(Address(X86::ebp, 2 * sizeof(void*)), output);
     1310    #endif
     1311#elif PLATFORM(ARM_V7)
     1312        push(ARM::r4);
     1313        push(ARM::r5);
     1314        push(ARM::r6);
     1315        move(ARM::r3, output);
    12971316#endif
    1298 #endif
    12991317    }
    13001318
    13011319    void generateReturn()
    13021320    {
    1303 #if PLATFORM(X86)
     1321#if PLATFORM(X86_64)
     1322        pop(X86::ebp);
     1323#elif PLATFORM(X86)
    13041324        pop(X86::esi);
    13051325        pop(X86::edi);
    13061326        pop(X86::ebx);
     1327        pop(X86::ebp);
     1328#elif PLATFORM(ARM_V7)
     1329        pop(ARM::r6);
     1330        pop(ARM::r5);
     1331        pop(ARM::r4);
    13071332#endif
    1308         pop(X86::ebp);
    13091333        ret();
    13101334    }
Note: See TracChangeset for help on using the changeset viewer.