LCOV - app.info - js/src/methodjit/StubCompiler.cpp

LCOV - code coverage report
| Current view: | directory - js/src/methodjit - StubCompiler.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 97 | 96 | 99.0 %
| Date: | 2012-04-07 | Functions: | 15 | 15 | 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                 :
          41                 : #include "StubCalls.h"
          42                 : #include "StubCompiler.h"
          43                 : #include "Compiler.h"
          44                 : #include "assembler/assembler/LinkBuffer.h"
          45                 : #include "FrameState-inl.h"
          46                 :
          47                 : using namespace js;
          48                 : using namespace mjit;
          49                 :
          50           95862 : StubCompiler::StubCompiler(JSContext *cx, mjit::Compiler &cc, FrameState &frame)
          51                 : : cx(cx),
          52                 :   cc(cc),
          53                 :   frame(frame),
          54                 :   generation(1),
          55                 :   lastGeneration(0),
          56                 :   exits(CompilerAllocPolicy(cx, cc)),
          57                 :   joins(CompilerAllocPolicy(cx, cc)),
          58                 :   scriptJoins(CompilerAllocPolicy(cx, cc)),
          59           95862 :   jumpList(SystemAllocPolicy())
          60                 : {
          61                 : #ifdef DEBUG
          62           95862 :     masm.setSpewPath(true);
          63                 : #endif
          64           95862 : }
          65                 :
          66                 : void
          67         2725199 : StubCompiler::linkExitDirect(Jump j, Label L)
          68                 : {
          69         2725199 :     exits.append(CrossPatch(j, L));
          70         2725199 : }
          71                 :
          72                 : JSC::MacroAssembler::Label
          73         1451270 : StubCompiler::syncExit(Uses uses)
          74                 : {
          75         1451270 :     JaegerSpew(JSpew_Insns, " ---- BEGIN SLOW MERGE CODE ---- \n");
          76                 :
          77         1451270 :     if (lastGeneration == generation) {
          78          115432 :         Jump j2 = masm.jump();
          79          115432 :         jumpList.append(j2);
          80                 :     }
          81                 :
          82         1451270 :     Label l = masm.label();
          83         1451270 :     frame.sync(masm, uses);
          84         1451270 :     lastGeneration = generation;
          85                 :
          86         1451270 :     JaegerSpew(JSpew_Insns, " ---- END SLOW MERGE CODE ---- \n");
          87                 :
          88                 :     return l;
          89                 : }
          90                 :
          91                 : JSC::MacroAssembler::Label
          92          381275 : StubCompiler::syncExitAndJump(Uses uses)
          93                 : {
          94          381275 :     Label l = syncExit(uses);
          95          381275 :     Jump j2 = masm.jump();
          96          381275 :     jumpList.append(j2);
          97                 :     /* Suppress jumping on next sync/link. */
          98          381275 :     generation++;
          99                 :     return l;
         100                 : }
         101                 :
         102                 : // Link an exit from the fast path to a slow path. This does two main things:
         103                 : // (a) links the given jump to the slow path, and (b) generates a prolog for
         104                 : // the slow path that syncs frame state for a slow call that uses |uses|
         105                 : // values from the top of the stack.
         106                 : //
         107                 : // The return value is the label for the start of the merge code. This is
         108                 : // the correct place to jump to in order to execute the slow path being
         109                 : // generated here.
         110                 : //
         111                 : // Note 1: Slow path generation is interleaved with fast path generation, but
         112                 : // the slow path goes into a separate buffer. The slow path code is appended
         113                 : // to the fast path code to keep it nearby in code memory.
         114                 : //
         115                 : // Note 2: A jump from the fast path to the slow path is called an "exit".
         116                 : //         A jump from the slow path to the fast path is called a "rejoin".
         117                 : JSC::MacroAssembler::Label
         118          825133 : StubCompiler::linkExit(Jump j, Uses uses)
         119                 : {
         120          825133 :     Label l = syncExit(uses);
         121          825133 :     linkExitDirect(j, l);
         122                 :     return l;
         123                 : }
         124                 :
         125                 : // Special version of linkExit that is used when there is a JavaScript
         126                 : // control-flow branch after the slow path. Our compilation strategy
         127                 : // requires the JS frame to be fully materialized in memory across branches.
         128                 : // This function does a linkExit and also fully materializes the frame.
         129                 : void
         130           33026 : StubCompiler::linkExitForBranch(Jump j)
         131                 : {
         132           33026 :     Label l = syncExit(Uses(frame.frameSlots()));
         133           33026 :     linkExitDirect(j, l);
         134           33026 : }
         135                 :
         136                 : void
         137         1379425 : StubCompiler::leave()
         138                 : {
         139         1379425 :     JaegerSpew(JSpew_Insns, " ---- BEGIN SLOW LEAVE CODE ---- \n");
         140         1876132 :     for (size_t i = 0; i < jumpList.length(); i++)
         141          496707 :         jumpList[i].linkTo(masm.label(), &masm);
         142         1379425 :     jumpList.clear();
         143         1379425 :     generation++;
         144         1379425 :     JaegerSpew(JSpew_Insns, " ---- END SLOW LEAVE CODE ---- \n");
         145         1379425 : }
         146                 :
         147                 : void
         148         1605194 : StubCompiler::rejoin(Changes changes)
         149                 : {
         150         1605194 :     JaegerSpew(JSpew_Insns, " ---- BEGIN SLOW RESTORE CODE ---- \n");
         151                 :
         152         1605194 :     frame.merge(masm, changes);
         153                 :
         154         1605194 :     unsigned index = crossJump(masm.jump(), cc.getLabel());
         155         1605194 :     if (cc.loop)
         156          365645 :         cc.loop->addJoin(index, false);
         157                 :
         158         1605194 :     JaegerSpew(JSpew_Insns, " ---- END SLOW RESTORE CODE ---- \n");
         159         1605194 : }
         160                 :
         161                 : void
         162          338861 : StubCompiler::linkRejoin(Jump j)
         163                 : {
         164          338861 :     crossJump(j, cc.getLabel());
         165          338861 : }
         166                 :
         167                 : typedef JSC::MacroAssembler::RegisterID RegisterID;
         168                 : typedef JSC::MacroAssembler::ImmPtr ImmPtr;
         169                 : typedef JSC::MacroAssembler::Imm32 Imm32;
         170                 : typedef JSC::MacroAssembler::DataLabelPtr DataLabelPtr;
         171                 :
         172                 : JSC::MacroAssembler::Call
         173         1997277 : StubCompiler::emitStubCall(void *ptr, RejoinState rejoin, Uses uses)
         174                 : {
         175         1997277 :     return emitStubCall(ptr, rejoin, uses, frame.totalDepth());
         176                 : }
         177                 :
         178                 : JSC::MacroAssembler::Call
         179         2095663 : StubCompiler::emitStubCall(void *ptr, RejoinState rejoin, Uses uses, int32_t slots)
         180                 : {
         181         2095663 :     JaegerSpew(JSpew_Insns, " ---- BEGIN SLOW CALL CODE ---- \n");
         182         2095663 :     masm.bumpStubCount(cc.script, cc.PC, Registers::tempCallReg());
         183         2095663 :     DataLabelPtr inlinePatch;
         184         2095663 :     Call cl = masm.fallibleVMCall(cx->typeInferenceEnabled(),
         185         4191326 :                                   ptr, cc.outerPC(), &inlinePatch, slots);
         186         2095663 :     JaegerSpew(JSpew_Insns, " ---- END SLOW CALL CODE ---- \n");
         187                 :
         188                 :     /* Add the call site for debugging and recompilation. */
         189                 :     Compiler::InternalCallSite site(masm.callReturnOffset(cl),
         190                 :                                     cc.inlineIndex(), cc.inlinePC(),
         191         2095663 :                                     rejoin, true);
         192         2095663 :     site.inlinePatch = inlinePatch;
         193                 :
         194                 :     /* Add a hook for restoring loop invariants if necessary. */
         195         2095663 :     if (cc.loop && cc.loop->generatingInvariants()) {
         196           30659 :         site.loopJumpLabel = masm.label();
         197           30659 :         Jump j = masm.jump();
         198           30659 :         Label l = masm.label();
         199                 :         /* MissedBoundsCheck* are not actually called, so f.regs need to be written before InvariantFailure. */
         200                 :         bool entry = (ptr == JS_FUNC_TO_DATA_PTR(void *, stubs::MissedBoundsCheckEntry))
         201           30659 :                   || (ptr == JS_FUNC_TO_DATA_PTR(void *, stubs::MissedBoundsCheckHead));
         202           30659 :         cc.loop->addInvariantCall(j, l, true, entry, cc.callSites.length(), uses);
         203                 :     }
         204                 :
         205         2095663 :     cc.addCallSite(site);
         206                 :     return cl;
         207                 : }
         208                 :
         209                 : void
         210           93652 : StubCompiler::fixCrossJumps(uint8_t *ncode, size_t offset, size_t total)
         211                 : {
         212          187304 :     JSC::LinkBuffer fast(ncode, total, JSC::METHOD_CODE);
         213          187304 :     JSC::LinkBuffer slow(ncode + offset, total - offset, JSC::METHOD_CODE);
         214                 :
         215         2818477 :     for (size_t i = 0; i < exits.length(); i++)
         216         2724825 :         fast.link(exits[i].from, slow.locationOf(exits[i].to));
         217                 :
         218          186512 :     for (size_t i = 0; i < scriptJoins.length(); i++) {
         219           92860 :         const CrossJumpInScript &cj = scriptJoins[i];
         220           92860 :         slow.link(cj.from, fast.locationOf(cc.labelOf(cj.pc, cj.inlineIndex)));
         221                 :     }
         222                 :
         223         2380661 :     for (size_t i = 0; i < joins.length(); i++)
         224         2287009 :         slow.link(joins[i].from, fast.locationOf(joins[i].to));
         225           93652 : }
         226                 :
         227                 : unsigned
         228         2287381 : StubCompiler::crossJump(Jump j, Label L)
         229                 : {
         230         2287381 :     joins.append(CrossPatch(j, L));
         231                 :
         232                 :     /* This won't underflow, as joins has space preallocated for some entries. */
         233         2287381 :     return joins.length() - 1;
         234                 : }
         235                 :
         236                 : bool
         237          138626 : StubCompiler::jumpInScript(Jump j, jsbytecode *target)
         238                 : {
         239          138626 :     if (cc.knownJump(target)) {
         240           45752 :         unsigned index = crossJump(j, cc.labelOf(target, cc.inlineIndex()));
         241           45752 :         if (cc.loop)
         242           36381 :             cc.loop->addJoin(index, false);
         243                 :     } else {
         244           92874 :         if (!scriptJoins.append(CrossJumpInScript(j, target, cc.inlineIndex())))
         245               0 :             return false;
         246           92874 :         if (cc.loop)
         247           44341 :             cc.loop->addJoin(scriptJoins.length() - 1, true);
         248                 :     }
         249          138626 :     return true;
         250                 : }
         251                 :
         252                 : void
         253           33831 : StubCompiler::patchJoin(unsigned i, bool script, Assembler::Address address, AnyRegisterID reg)
         254                 : {
         255           33831 :     Jump &j = script ? scriptJoins[i].from : joins[i].from;
         256           33831 :     j.linkTo(masm.label(), &masm);
         257                 :
         258           33831 :     if (reg.isReg())
         259           33400 :         masm.loadPayload(address, reg.reg());
         260                 :     else
         261             431 :         masm.loadDouble(address, reg.fpreg());
         262                 :
         263           33831 :     j = masm.jump();
         264           33831 : }

Generated by: LCOV version 1.7