js/src/jit/CompileInfo.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/CompileInfo.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,340 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jit_CompileInfo_h
    1.11 +#define jit_CompileInfo_h
    1.12 +
    1.13 +#include "jsfun.h"
    1.14 +
    1.15 +#include "jit/Registers.h"
    1.16 +#include "vm/ScopeObject.h"
    1.17 +
    1.18 +namespace js {
    1.19 +namespace jit {
    1.20 +
    1.21 +inline unsigned
    1.22 +StartArgSlot(JSScript *script)
    1.23 +{
    1.24 +    // Reserved slots:
    1.25 +    // Slot 0: Scope chain.
    1.26 +    // Slot 1: Return value.
    1.27 +
    1.28 +    // When needed:
    1.29 +    // Slot 2: Argumentsobject.
    1.30 +
    1.31 +    // Note: when updating this, please also update the assert in SnapshotWriter::startFrame
    1.32 +    return 2 + (script->argumentsHasVarBinding() ? 1 : 0);
    1.33 +}
    1.34 +
    1.35 +inline unsigned
    1.36 +CountArgSlots(JSScript *script, JSFunction *fun)
    1.37 +{
    1.38 +    // Slot x + 0: This value.
    1.39 +    // Slot x + 1: Argument 1.
    1.40 +    // ...
    1.41 +    // Slot x + n: Argument n.
    1.42 +
    1.43 +    // Note: when updating this, please also update the assert in SnapshotWriter::startFrame
    1.44 +    return StartArgSlot(script) + (fun ? fun->nargs() + 1 : 0);
    1.45 +}
    1.46 +
    1.47 +// Contains information about the compilation source for IR being generated.
    1.48 +class CompileInfo
    1.49 +{
    1.50 +  public:
    1.51 +    CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
    1.52 +                ExecutionMode executionMode, bool scriptNeedsArgsObj)
    1.53 +      : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
    1.54 +        executionMode_(executionMode), scriptNeedsArgsObj_(scriptNeedsArgsObj)
    1.55 +    {
    1.56 +        JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
    1.57 +
    1.58 +        // The function here can flow in from anywhere so look up the canonical
    1.59 +        // function to ensure that we do not try to embed a nursery pointer in
    1.60 +        // jit-code. Precisely because it can flow in from anywhere, it's not
    1.61 +        // guaranteed to be non-lazy. Hence, don't access its script!
    1.62 +        if (fun_) {
    1.63 +            fun_ = fun_->nonLazyScript()->functionNonDelazifying();
    1.64 +            JS_ASSERT(fun_->isTenured());
    1.65 +        }
    1.66 +
    1.67 +        osrStaticScope_ = osrPc ? script->getStaticScope(osrPc) : nullptr;
    1.68 +
    1.69 +        nimplicit_ = StartArgSlot(script)                   /* scope chain and argument obj */
    1.70 +                   + (fun ? 1 : 0);                         /* this */
    1.71 +        nargs_ = fun ? fun->nargs() : 0;
    1.72 +        nfixedvars_ = script->nfixedvars();
    1.73 +        nlocals_ = script->nfixed();
    1.74 +        nstack_ = script->nslots() - script->nfixed();
    1.75 +        nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
    1.76 +    }
    1.77 +
    1.78 +    CompileInfo(unsigned nlocals, ExecutionMode executionMode)
    1.79 +      : script_(nullptr), fun_(nullptr), osrPc_(nullptr), osrStaticScope_(nullptr),
    1.80 +        constructing_(false), executionMode_(executionMode), scriptNeedsArgsObj_(false)
    1.81 +    {
    1.82 +        nimplicit_ = 0;
    1.83 +        nargs_ = 0;
    1.84 +        nfixedvars_ = 0;
    1.85 +        nlocals_ = nlocals;
    1.86 +        nstack_ = 1;  /* For FunctionCompiler::pushPhiInput/popPhiOutput */
    1.87 +        nslots_ = nlocals_ + nstack_;
    1.88 +    }
    1.89 +
    1.90 +    JSScript *script() const {
    1.91 +        return script_;
    1.92 +    }
    1.93 +    JSFunction *funMaybeLazy() const {
    1.94 +        return fun_;
    1.95 +    }
    1.96 +    bool constructing() const {
    1.97 +        return constructing_;
    1.98 +    }
    1.99 +    jsbytecode *osrPc() {
   1.100 +        return osrPc_;
   1.101 +    }
   1.102 +    NestedScopeObject *osrStaticScope() const {
   1.103 +        return osrStaticScope_;
   1.104 +    }
   1.105 +
   1.106 +    bool hasOsrAt(jsbytecode *pc) {
   1.107 +        JS_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
   1.108 +        return pc == osrPc();
   1.109 +    }
   1.110 +
   1.111 +    jsbytecode *startPC() const {
   1.112 +        return script_->code();
   1.113 +    }
   1.114 +    jsbytecode *limitPC() const {
   1.115 +        return script_->codeEnd();
   1.116 +    }
   1.117 +
   1.118 +    const char *filename() const {
   1.119 +        return script_->filename();
   1.120 +    }
   1.121 +
   1.122 +    unsigned lineno() const {
   1.123 +        return script_->lineno();
   1.124 +    }
   1.125 +    unsigned lineno(jsbytecode *pc) const {
   1.126 +        return PCToLineNumber(script_, pc);
   1.127 +    }
   1.128 +
   1.129 +    // Script accessors based on PC.
   1.130 +
   1.131 +    JSAtom *getAtom(jsbytecode *pc) const {
   1.132 +        return script_->getAtom(GET_UINT32_INDEX(pc));
   1.133 +    }
   1.134 +
   1.135 +    PropertyName *getName(jsbytecode *pc) const {
   1.136 +        return script_->getName(GET_UINT32_INDEX(pc));
   1.137 +    }
   1.138 +
   1.139 +    inline RegExpObject *getRegExp(jsbytecode *pc) const;
   1.140 +
   1.141 +    JSObject *getObject(jsbytecode *pc) const {
   1.142 +        return script_->getObject(GET_UINT32_INDEX(pc));
   1.143 +    }
   1.144 +
   1.145 +    inline JSFunction *getFunction(jsbytecode *pc) const;
   1.146 +
   1.147 +    const Value &getConst(jsbytecode *pc) const {
   1.148 +        return script_->getConst(GET_UINT32_INDEX(pc));
   1.149 +    }
   1.150 +
   1.151 +    jssrcnote *getNote(GSNCache &gsn, jsbytecode *pc) const {
   1.152 +        return GetSrcNote(gsn, script(), pc);
   1.153 +    }
   1.154 +
   1.155 +    // Total number of slots: args, locals, and stack.
   1.156 +    unsigned nslots() const {
   1.157 +        return nslots_;
   1.158 +    }
   1.159 +
   1.160 +    // Number of slots needed for Scope chain, return value,
   1.161 +    // maybe argumentsobject and this value.
   1.162 +    unsigned nimplicit() const {
   1.163 +        return nimplicit_;
   1.164 +    }
   1.165 +    // Number of arguments (without counting this value).
   1.166 +    unsigned nargs() const {
   1.167 +        return nargs_;
   1.168 +    }
   1.169 +    // Number of slots needed for "fixed vars".  Note that this is only non-zero
   1.170 +    // for function code.
   1.171 +    unsigned nfixedvars() const {
   1.172 +        return nfixedvars_;
   1.173 +    }
   1.174 +    // Number of slots needed for all local variables.  This includes "fixed
   1.175 +    // vars" (see above) and also block-scoped locals.
   1.176 +    unsigned nlocals() const {
   1.177 +        return nlocals_;
   1.178 +    }
   1.179 +    unsigned ninvoke() const {
   1.180 +        return nslots_ - nstack_;
   1.181 +    }
   1.182 +
   1.183 +    uint32_t scopeChainSlot() const {
   1.184 +        JS_ASSERT(script());
   1.185 +        return 0;
   1.186 +    }
   1.187 +    uint32_t returnValueSlot() const {
   1.188 +        JS_ASSERT(script());
   1.189 +        return 1;
   1.190 +    }
   1.191 +    uint32_t argsObjSlot() const {
   1.192 +        JS_ASSERT(hasArguments());
   1.193 +        return 2;
   1.194 +    }
   1.195 +    uint32_t thisSlot() const {
   1.196 +        JS_ASSERT(funMaybeLazy());
   1.197 +        JS_ASSERT(nimplicit_ > 0);
   1.198 +        return nimplicit_ - 1;
   1.199 +    }
   1.200 +    uint32_t firstArgSlot() const {
   1.201 +        return nimplicit_;
   1.202 +    }
   1.203 +    uint32_t argSlotUnchecked(uint32_t i) const {
   1.204 +        // During initialization, some routines need to get at arg
   1.205 +        // slots regardless of how regular argument access is done.
   1.206 +        JS_ASSERT(i < nargs_);
   1.207 +        return nimplicit_ + i;
   1.208 +    }
   1.209 +    uint32_t argSlot(uint32_t i) const {
   1.210 +        // This should only be accessed when compiling functions for
   1.211 +        // which argument accesses don't need to go through the
   1.212 +        // argument object.
   1.213 +        JS_ASSERT(!argsObjAliasesFormals());
   1.214 +        return argSlotUnchecked(i);
   1.215 +    }
   1.216 +    uint32_t firstLocalSlot() const {
   1.217 +        return nimplicit_ + nargs_;
   1.218 +    }
   1.219 +    uint32_t localSlot(uint32_t i) const {
   1.220 +        return firstLocalSlot() + i;
   1.221 +    }
   1.222 +    uint32_t firstStackSlot() const {
   1.223 +        return firstLocalSlot() + nlocals();
   1.224 +    }
   1.225 +    uint32_t stackSlot(uint32_t i) const {
   1.226 +        return firstStackSlot() + i;
   1.227 +    }
   1.228 +
   1.229 +    uint32_t startArgSlot() const {
   1.230 +        JS_ASSERT(script());
   1.231 +        return StartArgSlot(script());
   1.232 +    }
   1.233 +    uint32_t endArgSlot() const {
   1.234 +        JS_ASSERT(script());
   1.235 +        return CountArgSlots(script(), funMaybeLazy());
   1.236 +    }
   1.237 +
   1.238 +    uint32_t totalSlots() const {
   1.239 +        JS_ASSERT(script() && funMaybeLazy());
   1.240 +        return nimplicit() + nargs() + nlocals();
   1.241 +    }
   1.242 +
   1.243 +    bool isSlotAliased(uint32_t index, NestedScopeObject *staticScope) const {
   1.244 +        JS_ASSERT(index >= startArgSlot());
   1.245 +
   1.246 +        if (funMaybeLazy() && index == thisSlot())
   1.247 +            return false;
   1.248 +
   1.249 +        uint32_t arg = index - firstArgSlot();
   1.250 +        if (arg < nargs())
   1.251 +            return script()->formalIsAliased(arg);
   1.252 +
   1.253 +        uint32_t local = index - firstLocalSlot();
   1.254 +        if (local < nlocals()) {
   1.255 +            // First, check if this local is a var.
   1.256 +            if (local < nfixedvars())
   1.257 +                return script()->varIsAliased(local);
   1.258 +
   1.259 +            // Otherwise, it might be part of a block scope.
   1.260 +            for (; staticScope; staticScope = staticScope->enclosingNestedScope()) {
   1.261 +                if (!staticScope->is<StaticBlockObject>())
   1.262 +                    continue;
   1.263 +                StaticBlockObject &blockObj = staticScope->as<StaticBlockObject>();
   1.264 +                if (blockObj.localOffset() < local) {
   1.265 +                    if (local - blockObj.localOffset() < blockObj.numVariables())
   1.266 +                        return blockObj.isAliased(local - blockObj.localOffset());
   1.267 +                    return false;
   1.268 +                }
   1.269 +            }
   1.270 +
   1.271 +            // In this static scope, this var is dead.
   1.272 +            return false;
   1.273 +        }
   1.274 +
   1.275 +        JS_ASSERT(index >= firstStackSlot());
   1.276 +        return false;
   1.277 +    }
   1.278 +
   1.279 +    bool isSlotAliasedAtEntry(uint32_t index) const {
   1.280 +        return isSlotAliased(index, nullptr);
   1.281 +    }
   1.282 +    bool isSlotAliasedAtOsr(uint32_t index) const {
   1.283 +        return isSlotAliased(index, osrStaticScope());
   1.284 +    }
   1.285 +
   1.286 +    bool hasArguments() const {
   1.287 +        return script()->argumentsHasVarBinding();
   1.288 +    }
   1.289 +    bool argumentsAliasesFormals() const {
   1.290 +        return script()->argumentsAliasesFormals();
   1.291 +    }
   1.292 +    bool needsArgsObj() const {
   1.293 +        return scriptNeedsArgsObj_;
   1.294 +    }
   1.295 +    bool argsObjAliasesFormals() const {
   1.296 +        return scriptNeedsArgsObj_ && !script()->strict();
   1.297 +    }
   1.298 +
   1.299 +    ExecutionMode executionMode() const {
   1.300 +        return executionMode_;
   1.301 +    }
   1.302 +
   1.303 +    bool executionModeIsAnalysis() const {
   1.304 +        return executionMode_ == DefinitePropertiesAnalysis || executionMode_ == ArgumentsUsageAnalysis;
   1.305 +    }
   1.306 +
   1.307 +    bool isParallelExecution() const {
   1.308 +        return executionMode_ == ParallelExecution;
   1.309 +    }
   1.310 +
   1.311 +    bool canOptimizeOutSlot(uint32_t i) const {
   1.312 +        if (script()->strict())
   1.313 +            return true;
   1.314 +
   1.315 +        // Function.arguments can be used to access all arguments in
   1.316 +        // non-strict scripts, so we can't optimize out any arguments.
   1.317 +        return !(firstArgSlot() <= i && i - firstArgSlot() < nargs());
   1.318 +    }
   1.319 +
   1.320 +  private:
   1.321 +    unsigned nimplicit_;
   1.322 +    unsigned nargs_;
   1.323 +    unsigned nfixedvars_;
   1.324 +    unsigned nlocals_;
   1.325 +    unsigned nstack_;
   1.326 +    unsigned nslots_;
   1.327 +    JSScript *script_;
   1.328 +    JSFunction *fun_;
   1.329 +    jsbytecode *osrPc_;
   1.330 +    NestedScopeObject *osrStaticScope_;
   1.331 +    bool constructing_;
   1.332 +    ExecutionMode executionMode_;
   1.333 +
   1.334 +    // Whether a script needs an arguments object is unstable over compilation
   1.335 +    // since the arguments optimization could be marked as failed on the main
   1.336 +    // thread, so cache a value here and use it throughout for consistency.
   1.337 +    bool scriptNeedsArgsObj_;
   1.338 +};
   1.339 +
   1.340 +} // namespace jit
   1.341 +} // namespace js
   1.342 +
   1.343 +#endif /* jit_CompileInfo_h */

mercurial