Changeset 41089 in webkit for trunk/JavaScriptCore/assembler


Ignore:
Timestamp:
Feb 19, 2009, 2:51:40 PM (16 years ago)
Author:
[email protected]
Message:

2009-02-19 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Fix for x86-64. Where the JavaScriptCore text segment lies outside
a 2gb range of the heap containing JIT generated code, callbacks
from JIT code to the stub functions in Interpreter will be incorrectly
linked.

No performance impact on Sunspider, 1% regression on v8-tests,
due to a 3% regression on richards.

  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::Call::Call): (JSC::AbstractMacroAssembler::Jump::link): (JSC::AbstractMacroAssembler::Jump::linkTo): (JSC::AbstractMacroAssembler::CodeLocationJump::relink): (JSC::AbstractMacroAssembler::CodeLocationCall::relink): (JSC::AbstractMacroAssembler::ProcessorReturnAddress::relinkCallerToFunction): (JSC::AbstractMacroAssembler::PatchBuffer::link): (JSC::AbstractMacroAssembler::PatchBuffer::linkTailRecursive): (JSC::AbstractMacroAssembler::differenceBetween):
  • assembler/MacroAssembler.h: (JSC::MacroAssembler::tailRecursiveCall): (JSC::MacroAssembler::makeTailRecursiveCall):
  • assembler/MacroAssemblerX86.h: (JSC::MacroAssemblerX86::call):
  • assembler/MacroAssemblerX86Common.h:
  • assembler/MacroAssemblerX86_64.h: (JSC::MacroAssemblerX86_64::call): (JSC::MacroAssemblerX86_64::moveWithPatch): (JSC::MacroAssemblerX86_64::branchPtrWithPatch): (JSC::MacroAssemblerX86_64::storePtrWithPatch):
  • assembler/X86Assembler.h: (JSC::X86Assembler::jmp_r): (JSC::X86Assembler::linkJump): (JSC::X86Assembler::patchJump): (JSC::X86Assembler::patchCall): (JSC::X86Assembler::linkCall): (JSC::X86Assembler::patchAddress):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::tryCTICachePutByID):
  • jit/JIT.cpp: (JSC::JIT::privateCompile): (JSC::JIT::privateCompileCTIMachineTrampolines):
  • jit/JIT.h:
  • jit/JITArithmetic.cpp: (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate): (JSC::JIT::compileBinaryArithOp):
  • jit/JITPropertyAccess.cpp: (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::privateCompileGetByIdSelf): (JSC::JIT::privateCompilePutByIdReplace):
Location:
trunk/JavaScriptCore/assembler
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r40879 r41089  
    266266        friend class AbstractMacroAssembler;
    267267    public:
     268        enum Flags {
     269            None = 0x0,
     270            Linkable = 0x1,
     271            Near = 0x2,
     272            LinkableNear = 0x3,
     273        };
     274
    268275        Call()
    269         {
    270         }
    271        
    272         Call(JmpSrc jmp, bool isRelative)
     276            : m_flags(None)
     277        {
     278        }
     279       
     280        Call(JmpSrc jmp, Flags flags)
    273281            : m_jmp(jmp)
    274 #ifndef NDEBUG
    275             , isRelative(isRelative)
    276 #endif
    277         {
    278 #ifdef NDEBUG
    279 #pragma unused(isRelative)
    280 #endif
    281         }
    282        
    283         void link(AbstractMacroAssembler<AssemblerType>* masm)
    284         {
    285             ASSERT(isRelative);
    286             masm->m_assembler.link(m_jmp, masm->m_assembler.label());
    287         }
    288        
    289         void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
    290         {
    291             ASSERT(isRelative);
    292             masm->m_assembler.link(m_jmp, label.m_label);
     282            , m_flags(flags)
     283        {
     284        }
     285
     286        bool isFlagSet(Flags flag)
     287        {
     288            return m_flags & flag;
     289        }
     290
     291        static Call fromTailJump(Jump jump)
     292        {
     293            return Call(jump.m_jmp, Linkable);
    293294        }
    294295
    295296    private:
    296297        JmpSrc m_jmp;
    297 #ifndef NDEBUG
    298         bool isRelative;
    299 #endif
     298        Flags m_flags;
    300299    };
    301300
     
    310309        template<class AssemblerType_T>
    311310        friend class AbstractMacroAssembler;
     311        friend class Call;
    312312    public:
    313313        Jump()
     
    322322        void link(AbstractMacroAssembler<AssemblerType>* masm)
    323323        {
    324             masm->m_assembler.link(m_jmp, masm->m_assembler.label());
     324            masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
    325325        }
    326326       
    327327        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
    328328        {
    329             masm->m_assembler.link(m_jmp, label.m_label);
     329            masm->m_assembler.linkJump(m_jmp, label.m_label);
    330330        }
    331331
     
    461461        void relink(CodeLocationLabel destination)
    462462        {
    463             AssemblerType::patchBranchOffset(reinterpret_cast<intptr_t>(this->m_location), destination.m_location);
     463            AssemblerType::patchJump(reinterpret_cast<intptr_t>(this->m_location), destination.m_location);
    464464        }
    465465
     
    485485        void relink(FunctionSig* function)
    486486        {
    487             AssemblerType::patchBranchOffset(reinterpret_cast<intptr_t>(this->m_location), reinterpret_cast<void*>(function));
     487            AssemblerType::patchMacroAssemblerCall(reinterpret_cast<intptr_t>(this->m_location), reinterpret_cast<void*>(function));
    488488        }
    489489
     
    502502    };
    503503
     504    // CodeLocationNearCall:
     505    //
     506    // A point in the JIT code at which there is a call instruction with near linkage.
     507    class CodeLocationNearCall : public CodeLocationCommon {
     508        friend class CodeLocationCommon;
     509        friend class PatchBuffer;
     510    public:
     511        CodeLocationNearCall()
     512        {
     513        }
     514
     515        template<typename FunctionSig>
     516        void relink(FunctionSig* function)
     517        {
     518            AssemblerType::patchCall(reinterpret_cast<intptr_t>(this->m_location), reinterpret_cast<void*>(function));
     519        }
     520
     521        // This methods returns the value that will be set as the return address
     522        // within a function that has been called from this call instruction.
     523        void* calleeReturnAddressValue()
     524        {
     525            return this->m_location;
     526        }
     527
     528    private:
     529        explicit CodeLocationNearCall(void* location)
     530            : CodeLocationCommon(location)
     531        {
     532        }
     533    };
     534
    504535    // CodeLocationDataLabel32:
    505536    //
     
    561592        void relinkCallerToFunction(FunctionSig* newCalleeFunction)
    562593        {
    563             AssemblerType::patchBranchOffset(reinterpret_cast<intptr_t>(this->m_location), reinterpret_cast<void*>(newCalleeFunction));
     594            AssemblerType::patchMacroAssemblerCall(reinterpret_cast<intptr_t>(this->m_location), reinterpret_cast<void*>(newCalleeFunction));
     595        }
     596       
     597        template<typename FunctionSig>
     598        void relinkNearCallerToFunction(FunctionSig* newCalleeFunction)
     599        {
     600            AssemblerType::patchCall(reinterpret_cast<intptr_t>(this->m_location), reinterpret_cast<void*>(newCalleeFunction));
    564601        }
    565602       
     
    616653        void link(Call call, FunctionSig* function)
    617654        {
    618             AssemblerType::link(m_code, call.m_jmp, reinterpret_cast<void*>(function));
     655            ASSERT(call.isFlagSet(Call::Linkable));
     656#if PLATFORM(X86_64)
     657            if (call.isFlagSet(Call::Near)) {
     658                AssemblerType::linkCall(m_code, call.m_jmp, reinterpret_cast<void*>(function));
     659            } else {
     660                intptr_t callLocation = reinterpret_cast<intptr_t>(AssemblerType::getRelocatedAddress(m_code, call.m_jmp));
     661                AssemblerType::patchMacroAssemblerCall(callLocation, reinterpret_cast<void*>(function));
     662            }
     663#else
     664            AssemblerType::linkCall(m_code, call.m_jmp, reinterpret_cast<void*>(function));
     665#endif
    619666        }
    620667       
     
    622669        void linkTailRecursive(Jump jump, FunctionSig* function)
    623670        {
    624             AssemblerType::link(m_code, jump.m_jmp, reinterpret_cast<void*>(function));
     671            AssemblerType::linkJump(m_code, jump.m_jmp, reinterpret_cast<void*>(function));
    625672        }
    626673
     
    628675        void linkTailRecursive(JumpList list, FunctionSig* function)
    629676        {
     677            for (unsigned i = 0; i < list.m_jumps.size(); ++i) {
     678                AssemblerType::linkJump(m_code, list.m_jumps[i].m_jmp, reinterpret_cast<void*>(function));
     679            }
     680        }
     681
     682        void link(Jump jump, CodeLocationLabel label)
     683        {
     684            AssemblerType::linkJump(m_code, jump.m_jmp, label.m_location);
     685        }
     686
     687        void link(JumpList list, CodeLocationLabel label)
     688        {
    630689            for (unsigned i = 0; i < list.m_jumps.size(); ++i)
    631                 AssemblerType::link(m_code, list.m_jumps[i].m_jmp, reinterpret_cast<void*>(function));
    632         }
    633 
    634         void link(Jump jump, CodeLocationLabel label)
    635         {
    636             AssemblerType::link(m_code, jump.m_jmp, label.m_location);
    637         }
    638 
    639         void link(JumpList list, CodeLocationLabel label)
    640         {
    641             for (unsigned i = 0; i < list.m_jumps.size(); ++i)
    642                 AssemblerType::link(m_code, list.m_jumps[i].m_jmp, label.m_location);
     690                AssemblerType::linkJump(m_code, list.m_jumps[i].m_jmp, label.m_location);
    643691        }
    644692
     
    652700        CodeLocationCall locationOf(Call call)
    653701        {
    654             ASSERT(call.isRelative);
     702            ASSERT(call.isFlagSet(Call::Linkable));
     703            ASSERT(!call.isFlagSet(Call::Near));
    655704            return CodeLocationCall(AssemblerType::getRelocatedAddress(m_code, call.m_jmp));
     705        }
     706
     707        CodeLocationNearCall locationOfNearCall(Call call)
     708        {
     709            ASSERT(call.isFlagSet(Call::Linkable));
     710            ASSERT(call.isFlagSet(Call::Near));
     711            return CodeLocationNearCall(AssemblerType::getRelocatedAddress(m_code, call.m_jmp));
    656712        }
    657713
     
    732788
    733789    ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
     790    {
     791        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
     792    }
     793
     794    ptrdiff_t differenceBetween(DataLabelPtr from, Call to)
    734795    {
    735796        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86.h

    r40660 r41089  
    4444    using MacroAssemblerX86Common::store32;
    4545    using MacroAssemblerX86Common::branch32;
     46    using MacroAssemblerX86Common::call;
    4647
    4748    void add32(Imm32 imm, RegisterID src, RegisterID dest)
     
    8283    }
    8384
     85    Call call()
     86    {
     87        return Call(m_assembler.call(), Call::Linkable);
     88    }
     89
     90    Call tailRecursiveCall()
     91    {
     92        return Call::fromTailJump(jump());
     93    }
     94
     95    Call makeTailRecursiveCall(Jump oldJump)
     96    {
     97        return Call::fromTailJump(oldJump);
     98    }
     99
     100
    84101    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
    85102    {
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r40963 r41089  
    530530    }
    531531
    532     Call call()
    533     {
    534         return Call(m_assembler.call(), true);
     532    Call nearCall()
     533    {
     534        return Call(m_assembler.call(), Call::LinkableNear);
    535535    }
    536536
    537537    Call call(RegisterID target)
    538538    {
    539         return Call(m_assembler.call(target), false);
     539        return Call(m_assembler.call(target), Call::None);
    540540    }
    541541
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86_64.h

    r40660 r41089  
    4646    using MacroAssemblerX86Common::load32;
    4747    using MacroAssemblerX86Common::store32;
     48    using MacroAssemblerX86Common::call;
    4849
    4950    void add32(Imm32 imm, AbsoluteAddress address)
     
    7879    }
    7980
     81    Call call()
     82    {
     83        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
     84        Call result = Call(m_assembler.call(scratchRegister), Call::Linkable);
     85        ASSERT(differenceBetween(label, result) == REPTACH_OFFSET_CALL_R11);
     86        return result;
     87    }
     88
     89    Call tailRecursiveCall()
     90    {
     91        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
     92        Jump newJump = Jump(m_assembler.jmp_r(scratchRegister));
     93        ASSERT(differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
     94        return Call::fromTailJump(newJump);
     95    }
     96
     97    Call makeTailRecursiveCall(Jump oldJump)
     98    {
     99        oldJump.link(this);
     100        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
     101        Jump newJump = Jump(m_assembler.jmp_r(scratchRegister));
     102        ASSERT(differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
     103        return Call::fromTailJump(newJump);
     104    }
    80105
    81106
     
    327352    }
    328353
     354    DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
     355    {
     356        m_assembler.movq_i64r(initialValue.asIntptr(), dest);
     357        return DataLabelPtr(this);
     358    }
     359
    329360    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
    330361    {
    331         m_assembler.movq_i64r(initialRightValue.asIntptr(), scratchRegister);
    332         dataLabel = DataLabelPtr(this);
     362        dataLabel = moveWithPatch(initialRightValue, scratchRegister);
    333363        return branchPtr(cond, left, scratchRegister);
    334364    }
     
    336366    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
    337367    {
    338         m_assembler.movq_i64r(initialRightValue.asIntptr(), scratchRegister);
    339         dataLabel = DataLabelPtr(this);
     368        dataLabel = moveWithPatch(initialRightValue, scratchRegister);
    340369        return branchPtr(cond, left, scratchRegister);
    341370    }
     
    343372    DataLabelPtr storePtrWithPatch(Address address)
    344373    {
    345         m_assembler.movq_i64r(0, scratchRegister);
    346         DataLabelPtr label(this);
     374        DataLabelPtr label = moveWithPatch(ImmPtr(0), scratchRegister);
    347375        storePtr(scratchRegister, address);
    348376        return label;
  • trunk/JavaScriptCore/assembler/X86Assembler.h

    r41051 r41089  
    4242inline bool CAN_SIGN_EXTEND_32_64(intptr_t value) { return value == (intptr_t)(int32_t)value; }
    4343inline bool CAN_SIGN_EXTEND_U32_64(intptr_t value) { return value == (intptr_t)(uint32_t)value; }
     44
     45#define REPTACH_OFFSET_CALL_R11 3
    4446#endif
    4547
     
    997999    }
    9981000   
    999     void jmp_r(RegisterID dst)
     1001    // Return a JmpSrc so we have a label to the jump, so we can use this
     1002    // To make a tail recursive call on x86-64.  The MacroAssembler
     1003    // really shouldn't wrap this as a Jump, since it can't be linked. :-/
     1004    JmpSrc jmp_r(RegisterID dst)
    10001005    {
    10011006        m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
     1007        return JmpSrc(m_formatter.size());
    10021008    }
    10031009   
     
    12251231    // Linking & patching:
    12261232
    1227     void link(JmpSrc from, JmpDst to)
     1233    void linkJump(JmpSrc from, JmpDst to)
    12281234    {
    12291235        ASSERT(to.m_offset != -1);
     
    12331239    }
    12341240   
    1235     static void patchAddress(void* code, JmpDst position, void* value)
    1236     {
    1237         ASSERT(position.m_offset != -1);
    1238        
    1239         reinterpret_cast<void**>(reinterpret_cast<ptrdiff_t>(code) + position.m_offset)[-1] = value;
    1240     }
    1241    
    1242     static void link(void* code, JmpSrc from, void* to)
     1241    static void linkJump(void* code, JmpSrc from, void* to)
    12431242    {
    12441243        ASSERT(from.m_offset != -1);
     
    12481247    }
    12491248   
    1250     static unsigned getCallReturnOffset(JmpSrc call)
    1251     {
    1252         ASSERT(call.m_offset >= 0);
    1253         return call.m_offset;
    1254     }
    1255 
    1256     static void* getRelocatedAddress(void* code, JmpSrc jump)
    1257     {
    1258         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
    1259     }
    1260    
    1261     static void* getRelocatedAddress(void* code, JmpDst destination)
    1262     {
    1263         ASSERT(destination.m_offset != -1);
    1264 
    1265         return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
    1266     }
    1267    
    1268     static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
    1269     {
    1270         return dst.m_offset - src.m_offset;
    1271     }
    1272    
    1273     static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
    1274     {
    1275         return dst.m_offset - src.m_offset;
    1276     }
    1277    
    1278     static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
    1279     {
    1280         return dst.m_offset - src.m_offset;
    1281     }
    1282    
    1283     static void patchImmediate(intptr_t where, int32_t value)
    1284     {
    1285         reinterpret_cast<int32_t*>(where)[-1] = value;
    1286     }
    1287    
    1288     static void patchPointer(intptr_t where, intptr_t value)
    1289     {
    1290         reinterpret_cast<intptr_t*>(where)[-1] = value;
    1291     }
    1292    
    1293     static void patchBranchOffset(intptr_t where, void* destination)
     1249    static void patchJump(intptr_t where, void* destination)
    12941250    {
    12951251        intptr_t offset = reinterpret_cast<intptr_t>(destination) - where;
    12961252        ASSERT(offset == static_cast<int32_t>(offset));
    12971253        reinterpret_cast<int32_t*>(where)[-1] = static_cast<int32_t>(offset);
     1254    }
     1255   
     1256#if PLATFORM(X86_64)
     1257    // FIXME: transition these functions out of here - the assembler
     1258    // shouldn't know that that this is mov/call pair using r11. :-/
     1259    static void patchMacroAssemblerCall(intptr_t where, void* destination)
     1260    {
     1261        patchAddress(reinterpret_cast<void*>(where - REPTACH_OFFSET_CALL_R11), JmpDst(0), destination);
     1262    }
     1263#else
     1264    static void patchMacroAssemblerCall(intptr_t where, void* destination)
     1265    {
     1266        intptr_t offset = reinterpret_cast<intptr_t>(destination) - where;
     1267        ASSERT(offset == static_cast<int32_t>(offset));
     1268        reinterpret_cast<int32_t*>(where)[-1] = static_cast<int32_t>(offset);
     1269    }
     1270#endif
     1271
     1272    void linkCall(JmpSrc from, JmpDst to)
     1273    {
     1274        ASSERT(to.m_offset != -1);
     1275        ASSERT(from.m_offset != -1);
     1276       
     1277        reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_formatter.data()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
     1278    }
     1279   
     1280    static void linkCall(void* code, JmpSrc from, void* to)
     1281    {
     1282        ASSERT(from.m_offset != -1);
     1283        ptrdiff_t linkOffset = reinterpret_cast<ptrdiff_t>(to) - (reinterpret_cast<ptrdiff_t>(code) + from.m_offset);
     1284        ASSERT(linkOffset == static_cast<int>(linkOffset));
     1285        reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + from.m_offset)[-1] = linkOffset;
     1286    }
     1287
     1288    static void patchCall(intptr_t where, void* destination)
     1289    {
     1290        intptr_t offset = reinterpret_cast<intptr_t>(destination) - where;
     1291        ASSERT(offset == static_cast<int32_t>(offset));
     1292        reinterpret_cast<int32_t*>(where)[-1] = static_cast<int32_t>(offset);
     1293    }
     1294
     1295    static void patchAddress(void* code, JmpDst position, void* value)
     1296    {
     1297        ASSERT(position.m_offset != -1);
     1298       
     1299        reinterpret_cast<void**>(reinterpret_cast<ptrdiff_t>(code) + position.m_offset)[-1] = value;
     1300    }
     1301   
     1302    static unsigned getCallReturnOffset(JmpSrc call)
     1303    {
     1304        ASSERT(call.m_offset >= 0);
     1305        return call.m_offset;
     1306    }
     1307
     1308    static void* getRelocatedAddress(void* code, JmpSrc jump)
     1309    {
     1310        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
     1311    }
     1312   
     1313    static void* getRelocatedAddress(void* code, JmpDst destination)
     1314    {
     1315        ASSERT(destination.m_offset != -1);
     1316
     1317        return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
     1318    }
     1319   
     1320    static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
     1321    {
     1322        return dst.m_offset - src.m_offset;
     1323    }
     1324   
     1325    static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
     1326    {
     1327        return dst.m_offset - src.m_offset;
     1328    }
     1329   
     1330    static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
     1331    {
     1332        return dst.m_offset - src.m_offset;
     1333    }
     1334   
     1335    static void patchImmediate(intptr_t where, int32_t value)
     1336    {
     1337        reinterpret_cast<int32_t*>(where)[-1] = value;
     1338    }
     1339   
     1340    static void patchPointer(intptr_t where, intptr_t value)
     1341    {
     1342        reinterpret_cast<intptr_t*>(where)[-1] = value;
    12981343    }
    12991344   
Note: See TracChangeset for help on using the changeset viewer.