LCOV - code coverage report
Current view: directory - js/src/methodjit - BaseCompiler.h (source / functions) Found Hit Coverage
Test: app.info Lines: 41 39 95.1 %
Date: 2012-06-02 Functions: 13 13 100.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=4 sw=4 et tw=99:
       3                 :  *
       4                 :  * ***** BEGIN LICENSE BLOCK *****
       5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       6                 :  *
       7                 :  * The contents of this file are subject to the Mozilla Public License Version
       8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       9                 :  * the License. You may obtain a copy of the License at
      10                 :  * http://www.mozilla.org/MPL/
      11                 :  *
      12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      14                 :  * for the specific language governing rights and limitations under the
      15                 :  * License.
      16                 :  *
      17                 :  * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
      18                 :  * May 28, 2008.
      19                 :  *
      20                 :  * The Initial Developer of the Original Code is
      21                 :  *   Brendan Eich <brendan@mozilla.org>
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   David Anderson <danderson@mozilla.com>
      25                 :  *   David Mandelin <dmandelin@mozilla.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : #if !defined jsjaeger_compilerbase_h__ && defined JS_METHODJIT
      41                 : #define jsjaeger_compilerbase_h__
      42                 : 
      43                 : #include "jscntxt.h"
      44                 : #include "assembler/assembler/MacroAssembler.h"
      45                 : #include "assembler/assembler/LinkBuffer.h"
      46                 : #include "assembler/assembler/RepatchBuffer.h"
      47                 : #include "assembler/jit/ExecutableAllocator.h"
      48                 : #include <limits.h>
      49                 : 
      50                 : #if defined JS_CPU_ARM
      51                 : # define POST_INST_OFFSET(__expr) ((__expr) - sizeof(ARMWord))
      52                 : #else
      53                 : # define POST_INST_OFFSET(__expr) (__expr)
      54                 : #endif
      55                 : 
      56                 : namespace js {
      57                 : namespace mjit {
      58                 : 
      59         2067462 : struct MacroAssemblerTypedefs {
      60                 :     typedef JSC::MacroAssembler::Label Label;
      61                 :     typedef JSC::MacroAssembler::Imm32 Imm32;
      62                 :     typedef JSC::MacroAssembler::ImmPtr ImmPtr;
      63                 :     typedef JSC::MacroAssembler::RegisterID RegisterID;
      64                 :     typedef JSC::MacroAssembler::FPRegisterID FPRegisterID;
      65                 :     typedef JSC::MacroAssembler::Address Address;
      66                 :     typedef JSC::MacroAssembler::BaseIndex BaseIndex;
      67                 :     typedef JSC::MacroAssembler::AbsoluteAddress AbsoluteAddress;
      68                 :     typedef JSC::MacroAssembler MacroAssembler;
      69                 :     typedef JSC::MacroAssembler::Jump Jump;
      70                 :     typedef JSC::MacroAssembler::JumpList JumpList;
      71                 :     typedef JSC::MacroAssembler::Call Call;
      72                 :     typedef JSC::MacroAssembler::DataLabelPtr DataLabelPtr;
      73                 :     typedef JSC::MacroAssembler::DataLabel32 DataLabel32;
      74                 :     typedef JSC::FunctionPtr FunctionPtr;
      75                 :     typedef JSC::RepatchBuffer RepatchBuffer;
      76                 :     typedef JSC::CodeLocationLabel CodeLocationLabel;
      77                 :     typedef JSC::CodeLocationDataLabel32 CodeLocationDataLabel32;
      78                 :     typedef JSC::CodeLocationDataLabelPtr CodeLocationDataLabelPtr;
      79                 :     typedef JSC::CodeLocationJump CodeLocationJump;
      80                 :     typedef JSC::CodeLocationCall CodeLocationCall;
      81                 :     typedef JSC::CodeLocationInstruction CodeLocationInstruction;
      82                 :     typedef JSC::ReturnAddressPtr ReturnAddressPtr;
      83                 :     typedef JSC::MacroAssemblerCodePtr MacroAssemblerCodePtr;
      84                 :     typedef JSC::JITCode JITCode;
      85                 : #if defined JS_CPU_ARM
      86                 :     typedef JSC::ARMWord ARMWord;
      87                 : #endif
      88                 : };
      89                 : 
      90                 : class BaseCompiler : public MacroAssemblerTypedefs
      91                 : {
      92                 :   protected:
      93                 :     JSContext *cx;
      94                 : 
      95                 :   public:
      96                 :     BaseCompiler() : cx(NULL)
      97                 :     { }
      98                 : 
      99         1183264 :     BaseCompiler(JSContext *cx) : cx(cx)
     100         1183264 :     { }
     101                 : };
     102                 : 
     103                 : #ifdef JS_CPU_X64
     104                 : inline bool
     105                 : VerifyRange(void *start1, size_t size1, void *start2, size_t size2)
     106                 : {
     107                 :     uintptr_t end1 = uintptr_t(start1) + size1;
     108                 :     uintptr_t end2 = uintptr_t(start2) + size2;
     109                 : 
     110                 :     uintptr_t lowest = JS_MIN(uintptr_t(start1), uintptr_t(start2));
     111                 :     uintptr_t highest = JS_MAX(end1, end2);
     112                 : 
     113                 :     return (highest - lowest < INT_MAX);
     114                 : }
     115                 : #endif
     116                 : 
     117                 : // This class wraps JSC::LinkBuffer for Mozilla-specific memory handling.
     118                 : // Every return |false| guarantees an OOM that has been correctly propagated,
     119                 : // and should continue to propagate.
     120                 : class LinkerHelper : public JSC::LinkBuffer
     121                 : {
     122                 :   protected:
     123                 :     Assembler &masm;
     124                 : #ifdef DEBUG
     125                 :     bool verifiedRange;
     126                 : #endif
     127                 : 
     128                 :   public:
     129          306058 :     LinkerHelper(Assembler &masm, JSC::CodeKind kind) : JSC::LinkBuffer(kind)
     130                 :         , masm(masm)
     131                 : #ifdef DEBUG
     132          306058 :         , verifiedRange(false)
     133                 : #endif
     134          306058 :     { }
     135                 : 
     136          612116 :     ~LinkerHelper() {
     137          306058 :         JS_ASSERT(verifiedRange);
     138          306058 :     }
     139                 : 
     140          566218 :     bool verifyRange(const JSC::JITCode &other) {
     141                 : #ifdef DEBUG
     142          566218 :         verifiedRange = true;
     143                 : #endif
     144                 : #ifdef JS_CPU_X64
     145                 :         return VerifyRange(m_code, m_size, other.start(), other.size());
     146                 : #else
     147          566218 :         return true;
     148                 : #endif
     149                 :     }
     150                 : 
     151          305824 :     bool verifyRange(JITChunk *chunk) {
     152                 :         return verifyRange(JSC::JITCode(chunk->code.m_code.executableAddress(),
     153          305824 :                                         chunk->code.m_size));
     154                 :     }
     155                 : 
     156          306058 :     JSC::ExecutablePool *init(JSContext *cx) {
     157                 :         // The pool is incref'd after this call, so it's necessary to release()
     158                 :         // on any failure.
     159          306058 :         JSScript *script = cx->fp()->script();
     160          306058 :         JSC::ExecutableAllocator *allocator = script->compartment()->jaegerCompartment()->execAlloc();
     161          306058 :         allocator->setDestroyCallback(Probes::discardExecutableRegion);
     162                 :         JSC::ExecutablePool *pool;
     163          306058 :         m_code = executableAllocAndCopy(masm, allocator, &pool);
     164          306058 :         if (!m_code) {
     165               0 :             js_ReportOutOfMemory(cx);
     166               0 :             return NULL;
     167                 :         }
     168          306058 :         m_size = masm.size();   // must come after call to executableAllocAndCopy()!
     169          306058 :         return pool;
     170                 :     }
     171                 : 
     172          303936 :     JSC::CodeLocationLabel finalize(VMFrame &f) {
     173          303936 :         masm.finalize(*this);
     174          303936 :         JSC::CodeLocationLabel label = finalizeCodeAddendum();
     175                 :         Probes::registerICCode(f.cx, f.jit(), f.script(), f.pc(),
     176          303936 :                                label.executableAddress(), masm.size());
     177                 :         return label;
     178                 :     }
     179                 : 
     180           17862 :     void maybeLink(MaybeJump jump, JSC::CodeLocationLabel label) {
     181           17862 :         if (!jump.isSet())
     182           11072 :             return;
     183            6790 :         link(jump.get(), label);
     184                 :     }
     185                 : 
     186          245847 :     size_t size() const {
     187          245847 :         return m_size;
     188                 :     }
     189                 : };
     190                 : 
     191                 : class NativeStubLinker : public LinkerHelper
     192           35521 : {
     193                 :   public:
     194                 : #ifdef JS_CPU_X64
     195                 :     typedef JSC::MacroAssembler::DataLabelPtr FinalJump;
     196                 : #else
     197                 :     typedef JSC::MacroAssembler::Jump FinalJump;
     198                 : #endif
     199                 : 
     200           35521 :     NativeStubLinker(Assembler &masm, JITChunk *chunk, jsbytecode *pc, FinalJump done)
     201           35521 :         : LinkerHelper(masm, JSC::METHOD_CODE), chunk(chunk), pc(pc), done(done)
     202           35521 :     {}
     203                 : 
     204                 :     bool init(JSContext *cx);
     205                 : 
     206           35521 :     void patchJump(JSC::CodeLocationLabel target) {
     207                 : #ifdef JS_CPU_X64
     208                 :         patch(done, target);
     209                 : #else
     210           35521 :         link(done, target);
     211                 : #endif
     212           35521 :     }
     213                 : 
     214                 :   private:
     215                 :     JITChunk *chunk;
     216                 :     jsbytecode *pc;
     217                 :     FinalJump done;
     218                 : };
     219                 : 
     220                 : bool
     221                 : NativeStubEpilogue(VMFrame &f, Assembler &masm, NativeStubLinker::FinalJump *result,
     222                 :                    int32_t initialFrameDepth, int32_t vpOffset,
     223                 :                    MaybeRegisterID typeReg, MaybeRegisterID dataReg);
     224                 : 
     225                 : /*
     226                 :  * On ARM, we periodically flush a constant pool into the instruction stream
     227                 :  * where constants are found using PC-relative addressing. This is necessary
     228                 :  * because the fixed-width instruction set doesn't support wide immediates.
     229                 :  *
     230                 :  * ICs perform repatching on the inline (fast) path by knowing small and
     231                 :  * generally fixed code location offset values where the patchable instructions
     232                 :  * live. Dumping a huge constant pool into the middle of an IC's inline path
     233                 :  * makes the distance between emitted instructions potentially variable and/or
     234                 :  * large, which makes the IC offsets invalid. We must reserve contiguous space
     235                 :  * up front to prevent this from happening.
     236                 :  */
     237                 : #ifdef JS_CPU_ARM
     238                 : template <size_t reservedSpace>
     239                 : class AutoReserveICSpace {
     240                 :     typedef Assembler::Label Label;
     241                 : 
     242                 :     Assembler           &masm;
     243                 :     bool                didCheck;
     244                 :     bool                *overflowSpace;
     245                 :     int                 flushCount;
     246                 : 
     247                 :   public:
     248                 :     AutoReserveICSpace(Assembler &masm, bool *overflowSpace)
     249                 :         : masm(masm), didCheck(false), overflowSpace(overflowSpace)
     250                 :     {
     251                 :         masm.ensureSpace(reservedSpace);
     252                 :         flushCount = masm.flushCount();
     253                 :     }
     254                 : 
     255                 :     /* Allow manual IC space checks so that non-patchable code at the end of an IC section can be
     256                 :      * free to use constant pools. */
     257                 :     void check() {
     258                 :         JS_ASSERT(!didCheck);
     259                 :         didCheck = true;
     260                 : 
     261                 :         if (masm.flushCount() != flushCount)
     262                 :             *overflowSpace = true;
     263                 :     }
     264                 : 
     265                 :     ~AutoReserveICSpace() {
     266                 :         /* Automatically check the IC space if we didn't already do it manually. */
     267                 :         if (!didCheck) {
     268                 :             check();
     269                 :         }
     270                 :     }
     271                 : };
     272                 : 
     273                 : # define RESERVE_IC_SPACE(__masm)       AutoReserveICSpace<256> arics(__masm, &this->overflowICSpace)
     274                 : # define CHECK_IC_SPACE()               arics.check()
     275                 : 
     276                 : /* The OOL path can need a lot of space because we save and restore a lot of registers. The actual
     277                 :  * sequene varies. However, dumping the literal pool before an OOL block is probably a good idea
     278                 :  * anyway, as we branch directly to the start of the block from the fast path. */
     279                 : # define RESERVE_OOL_SPACE(__masm)      AutoReserveICSpace<2048> arics_ool(__masm, &this->overflowICSpace)
     280                 : 
     281                 : /* Allow the OOL patch to be checked before object destruction. Often, non-patchable epilogues or
     282                 :  * rejoining sequences are emitted, and it isn't necessary to protect these from literal pools. */
     283                 : # define CHECK_OOL_SPACE()              arics_ool.check()
     284                 : #else
     285                 : # define RESERVE_IC_SPACE(__masm)       /* Do nothing. */
     286                 : # define CHECK_IC_SPACE()               /* Do nothing. */
     287                 : # define RESERVE_OOL_SPACE(__masm)      /* Do nothing. */
     288                 : # define CHECK_OOL_SPACE()              /* Do nothing. */
     289                 : #endif
     290                 : 
     291                 : } /* namespace js */
     292                 : } /* namespace mjit */
     293                 : 
     294                 : #endif

Generated by: LCOV version 1.7