js/src/jit/CompileInfo.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef jit_CompileInfo_h
michael@0 8 #define jit_CompileInfo_h
michael@0 9
michael@0 10 #include "jsfun.h"
michael@0 11
michael@0 12 #include "jit/Registers.h"
michael@0 13 #include "vm/ScopeObject.h"
michael@0 14
michael@0 15 namespace js {
michael@0 16 namespace jit {
michael@0 17
michael@0 18 inline unsigned
michael@0 19 StartArgSlot(JSScript *script)
michael@0 20 {
michael@0 21 // Reserved slots:
michael@0 22 // Slot 0: Scope chain.
michael@0 23 // Slot 1: Return value.
michael@0 24
michael@0 25 // When needed:
michael@0 26 // Slot 2: Argumentsobject.
michael@0 27
michael@0 28 // Note: when updating this, please also update the assert in SnapshotWriter::startFrame
michael@0 29 return 2 + (script->argumentsHasVarBinding() ? 1 : 0);
michael@0 30 }
michael@0 31
michael@0 32 inline unsigned
michael@0 33 CountArgSlots(JSScript *script, JSFunction *fun)
michael@0 34 {
michael@0 35 // Slot x + 0: This value.
michael@0 36 // Slot x + 1: Argument 1.
michael@0 37 // ...
michael@0 38 // Slot x + n: Argument n.
michael@0 39
michael@0 40 // Note: when updating this, please also update the assert in SnapshotWriter::startFrame
michael@0 41 return StartArgSlot(script) + (fun ? fun->nargs() + 1 : 0);
michael@0 42 }
michael@0 43
michael@0 44 // Contains information about the compilation source for IR being generated.
michael@0 45 class CompileInfo
michael@0 46 {
michael@0 47 public:
michael@0 48 CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
michael@0 49 ExecutionMode executionMode, bool scriptNeedsArgsObj)
michael@0 50 : script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
michael@0 51 executionMode_(executionMode), scriptNeedsArgsObj_(scriptNeedsArgsObj)
michael@0 52 {
michael@0 53 JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
michael@0 54
michael@0 55 // The function here can flow in from anywhere so look up the canonical
michael@0 56 // function to ensure that we do not try to embed a nursery pointer in
michael@0 57 // jit-code. Precisely because it can flow in from anywhere, it's not
michael@0 58 // guaranteed to be non-lazy. Hence, don't access its script!
michael@0 59 if (fun_) {
michael@0 60 fun_ = fun_->nonLazyScript()->functionNonDelazifying();
michael@0 61 JS_ASSERT(fun_->isTenured());
michael@0 62 }
michael@0 63
michael@0 64 osrStaticScope_ = osrPc ? script->getStaticScope(osrPc) : nullptr;
michael@0 65
michael@0 66 nimplicit_ = StartArgSlot(script) /* scope chain and argument obj */
michael@0 67 + (fun ? 1 : 0); /* this */
michael@0 68 nargs_ = fun ? fun->nargs() : 0;
michael@0 69 nfixedvars_ = script->nfixedvars();
michael@0 70 nlocals_ = script->nfixed();
michael@0 71 nstack_ = script->nslots() - script->nfixed();
michael@0 72 nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
michael@0 73 }
michael@0 74
michael@0 75 CompileInfo(unsigned nlocals, ExecutionMode executionMode)
michael@0 76 : script_(nullptr), fun_(nullptr), osrPc_(nullptr), osrStaticScope_(nullptr),
michael@0 77 constructing_(false), executionMode_(executionMode), scriptNeedsArgsObj_(false)
michael@0 78 {
michael@0 79 nimplicit_ = 0;
michael@0 80 nargs_ = 0;
michael@0 81 nfixedvars_ = 0;
michael@0 82 nlocals_ = nlocals;
michael@0 83 nstack_ = 1; /* For FunctionCompiler::pushPhiInput/popPhiOutput */
michael@0 84 nslots_ = nlocals_ + nstack_;
michael@0 85 }
michael@0 86
michael@0 87 JSScript *script() const {
michael@0 88 return script_;
michael@0 89 }
michael@0 90 JSFunction *funMaybeLazy() const {
michael@0 91 return fun_;
michael@0 92 }
michael@0 93 bool constructing() const {
michael@0 94 return constructing_;
michael@0 95 }
michael@0 96 jsbytecode *osrPc() {
michael@0 97 return osrPc_;
michael@0 98 }
michael@0 99 NestedScopeObject *osrStaticScope() const {
michael@0 100 return osrStaticScope_;
michael@0 101 }
michael@0 102
michael@0 103 bool hasOsrAt(jsbytecode *pc) {
michael@0 104 JS_ASSERT(JSOp(*pc) == JSOP_LOOPENTRY);
michael@0 105 return pc == osrPc();
michael@0 106 }
michael@0 107
michael@0 108 jsbytecode *startPC() const {
michael@0 109 return script_->code();
michael@0 110 }
michael@0 111 jsbytecode *limitPC() const {
michael@0 112 return script_->codeEnd();
michael@0 113 }
michael@0 114
michael@0 115 const char *filename() const {
michael@0 116 return script_->filename();
michael@0 117 }
michael@0 118
michael@0 119 unsigned lineno() const {
michael@0 120 return script_->lineno();
michael@0 121 }
michael@0 122 unsigned lineno(jsbytecode *pc) const {
michael@0 123 return PCToLineNumber(script_, pc);
michael@0 124 }
michael@0 125
michael@0 126 // Script accessors based on PC.
michael@0 127
michael@0 128 JSAtom *getAtom(jsbytecode *pc) const {
michael@0 129 return script_->getAtom(GET_UINT32_INDEX(pc));
michael@0 130 }
michael@0 131
michael@0 132 PropertyName *getName(jsbytecode *pc) const {
michael@0 133 return script_->getName(GET_UINT32_INDEX(pc));
michael@0 134 }
michael@0 135
michael@0 136 inline RegExpObject *getRegExp(jsbytecode *pc) const;
michael@0 137
michael@0 138 JSObject *getObject(jsbytecode *pc) const {
michael@0 139 return script_->getObject(GET_UINT32_INDEX(pc));
michael@0 140 }
michael@0 141
michael@0 142 inline JSFunction *getFunction(jsbytecode *pc) const;
michael@0 143
michael@0 144 const Value &getConst(jsbytecode *pc) const {
michael@0 145 return script_->getConst(GET_UINT32_INDEX(pc));
michael@0 146 }
michael@0 147
michael@0 148 jssrcnote *getNote(GSNCache &gsn, jsbytecode *pc) const {
michael@0 149 return GetSrcNote(gsn, script(), pc);
michael@0 150 }
michael@0 151
michael@0 152 // Total number of slots: args, locals, and stack.
michael@0 153 unsigned nslots() const {
michael@0 154 return nslots_;
michael@0 155 }
michael@0 156
michael@0 157 // Number of slots needed for Scope chain, return value,
michael@0 158 // maybe argumentsobject and this value.
michael@0 159 unsigned nimplicit() const {
michael@0 160 return nimplicit_;
michael@0 161 }
michael@0 162 // Number of arguments (without counting this value).
michael@0 163 unsigned nargs() const {
michael@0 164 return nargs_;
michael@0 165 }
michael@0 166 // Number of slots needed for "fixed vars". Note that this is only non-zero
michael@0 167 // for function code.
michael@0 168 unsigned nfixedvars() const {
michael@0 169 return nfixedvars_;
michael@0 170 }
michael@0 171 // Number of slots needed for all local variables. This includes "fixed
michael@0 172 // vars" (see above) and also block-scoped locals.
michael@0 173 unsigned nlocals() const {
michael@0 174 return nlocals_;
michael@0 175 }
michael@0 176 unsigned ninvoke() const {
michael@0 177 return nslots_ - nstack_;
michael@0 178 }
michael@0 179
michael@0 180 uint32_t scopeChainSlot() const {
michael@0 181 JS_ASSERT(script());
michael@0 182 return 0;
michael@0 183 }
michael@0 184 uint32_t returnValueSlot() const {
michael@0 185 JS_ASSERT(script());
michael@0 186 return 1;
michael@0 187 }
michael@0 188 uint32_t argsObjSlot() const {
michael@0 189 JS_ASSERT(hasArguments());
michael@0 190 return 2;
michael@0 191 }
michael@0 192 uint32_t thisSlot() const {
michael@0 193 JS_ASSERT(funMaybeLazy());
michael@0 194 JS_ASSERT(nimplicit_ > 0);
michael@0 195 return nimplicit_ - 1;
michael@0 196 }
michael@0 197 uint32_t firstArgSlot() const {
michael@0 198 return nimplicit_;
michael@0 199 }
michael@0 200 uint32_t argSlotUnchecked(uint32_t i) const {
michael@0 201 // During initialization, some routines need to get at arg
michael@0 202 // slots regardless of how regular argument access is done.
michael@0 203 JS_ASSERT(i < nargs_);
michael@0 204 return nimplicit_ + i;
michael@0 205 }
michael@0 206 uint32_t argSlot(uint32_t i) const {
michael@0 207 // This should only be accessed when compiling functions for
michael@0 208 // which argument accesses don't need to go through the
michael@0 209 // argument object.
michael@0 210 JS_ASSERT(!argsObjAliasesFormals());
michael@0 211 return argSlotUnchecked(i);
michael@0 212 }
michael@0 213 uint32_t firstLocalSlot() const {
michael@0 214 return nimplicit_ + nargs_;
michael@0 215 }
michael@0 216 uint32_t localSlot(uint32_t i) const {
michael@0 217 return firstLocalSlot() + i;
michael@0 218 }
michael@0 219 uint32_t firstStackSlot() const {
michael@0 220 return firstLocalSlot() + nlocals();
michael@0 221 }
michael@0 222 uint32_t stackSlot(uint32_t i) const {
michael@0 223 return firstStackSlot() + i;
michael@0 224 }
michael@0 225
michael@0 226 uint32_t startArgSlot() const {
michael@0 227 JS_ASSERT(script());
michael@0 228 return StartArgSlot(script());
michael@0 229 }
michael@0 230 uint32_t endArgSlot() const {
michael@0 231 JS_ASSERT(script());
michael@0 232 return CountArgSlots(script(), funMaybeLazy());
michael@0 233 }
michael@0 234
michael@0 235 uint32_t totalSlots() const {
michael@0 236 JS_ASSERT(script() && funMaybeLazy());
michael@0 237 return nimplicit() + nargs() + nlocals();
michael@0 238 }
michael@0 239
michael@0 240 bool isSlotAliased(uint32_t index, NestedScopeObject *staticScope) const {
michael@0 241 JS_ASSERT(index >= startArgSlot());
michael@0 242
michael@0 243 if (funMaybeLazy() && index == thisSlot())
michael@0 244 return false;
michael@0 245
michael@0 246 uint32_t arg = index - firstArgSlot();
michael@0 247 if (arg < nargs())
michael@0 248 return script()->formalIsAliased(arg);
michael@0 249
michael@0 250 uint32_t local = index - firstLocalSlot();
michael@0 251 if (local < nlocals()) {
michael@0 252 // First, check if this local is a var.
michael@0 253 if (local < nfixedvars())
michael@0 254 return script()->varIsAliased(local);
michael@0 255
michael@0 256 // Otherwise, it might be part of a block scope.
michael@0 257 for (; staticScope; staticScope = staticScope->enclosingNestedScope()) {
michael@0 258 if (!staticScope->is<StaticBlockObject>())
michael@0 259 continue;
michael@0 260 StaticBlockObject &blockObj = staticScope->as<StaticBlockObject>();
michael@0 261 if (blockObj.localOffset() < local) {
michael@0 262 if (local - blockObj.localOffset() < blockObj.numVariables())
michael@0 263 return blockObj.isAliased(local - blockObj.localOffset());
michael@0 264 return false;
michael@0 265 }
michael@0 266 }
michael@0 267
michael@0 268 // In this static scope, this var is dead.
michael@0 269 return false;
michael@0 270 }
michael@0 271
michael@0 272 JS_ASSERT(index >= firstStackSlot());
michael@0 273 return false;
michael@0 274 }
michael@0 275
michael@0 276 bool isSlotAliasedAtEntry(uint32_t index) const {
michael@0 277 return isSlotAliased(index, nullptr);
michael@0 278 }
michael@0 279 bool isSlotAliasedAtOsr(uint32_t index) const {
michael@0 280 return isSlotAliased(index, osrStaticScope());
michael@0 281 }
michael@0 282
michael@0 283 bool hasArguments() const {
michael@0 284 return script()->argumentsHasVarBinding();
michael@0 285 }
michael@0 286 bool argumentsAliasesFormals() const {
michael@0 287 return script()->argumentsAliasesFormals();
michael@0 288 }
michael@0 289 bool needsArgsObj() const {
michael@0 290 return scriptNeedsArgsObj_;
michael@0 291 }
michael@0 292 bool argsObjAliasesFormals() const {
michael@0 293 return scriptNeedsArgsObj_ && !script()->strict();
michael@0 294 }
michael@0 295
michael@0 296 ExecutionMode executionMode() const {
michael@0 297 return executionMode_;
michael@0 298 }
michael@0 299
michael@0 300 bool executionModeIsAnalysis() const {
michael@0 301 return executionMode_ == DefinitePropertiesAnalysis || executionMode_ == ArgumentsUsageAnalysis;
michael@0 302 }
michael@0 303
michael@0 304 bool isParallelExecution() const {
michael@0 305 return executionMode_ == ParallelExecution;
michael@0 306 }
michael@0 307
michael@0 308 bool canOptimizeOutSlot(uint32_t i) const {
michael@0 309 if (script()->strict())
michael@0 310 return true;
michael@0 311
michael@0 312 // Function.arguments can be used to access all arguments in
michael@0 313 // non-strict scripts, so we can't optimize out any arguments.
michael@0 314 return !(firstArgSlot() <= i && i - firstArgSlot() < nargs());
michael@0 315 }
michael@0 316
michael@0 317 private:
michael@0 318 unsigned nimplicit_;
michael@0 319 unsigned nargs_;
michael@0 320 unsigned nfixedvars_;
michael@0 321 unsigned nlocals_;
michael@0 322 unsigned nstack_;
michael@0 323 unsigned nslots_;
michael@0 324 JSScript *script_;
michael@0 325 JSFunction *fun_;
michael@0 326 jsbytecode *osrPc_;
michael@0 327 NestedScopeObject *osrStaticScope_;
michael@0 328 bool constructing_;
michael@0 329 ExecutionMode executionMode_;
michael@0 330
michael@0 331 // Whether a script needs an arguments object is unstable over compilation
michael@0 332 // since the arguments optimization could be marked as failed on the main
michael@0 333 // thread, so cache a value here and use it throughout for consistency.
michael@0 334 bool scriptNeedsArgsObj_;
michael@0 335 };
michael@0 336
michael@0 337 } // namespace jit
michael@0 338 } // namespace js
michael@0 339
michael@0 340 #endif /* jit_CompileInfo_h */

mercurial