js/src/jit/BaselineFrame.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_BaselineFrame_h
michael@0 8 #define jit_BaselineFrame_h
michael@0 9
michael@0 10 #ifdef JS_ION
michael@0 11
michael@0 12 #include "jit/IonFrames.h"
michael@0 13 #include "vm/Stack.h"
michael@0 14
michael@0 15 namespace js {
michael@0 16 namespace jit {
michael@0 17
michael@0 18 struct BaselineDebugModeOSRInfo;
michael@0 19
michael@0 20 // The stack looks like this, fp is the frame pointer:
michael@0 21 //
michael@0 22 // fp+y arguments
michael@0 23 // fp+x IonJSFrameLayout (frame header)
michael@0 24 // fp => saved frame pointer
michael@0 25 // fp-x BaselineFrame
michael@0 26 // locals
michael@0 27 // stack values
michael@0 28
michael@0 29 // Eval frames
michael@0 30 //
michael@0 31 // Like js::InterpreterFrame, every BaselineFrame is either a global frame
michael@0 32 // or a function frame. Both global and function frames can optionally
michael@0 33 // be "eval frames". The callee token for eval function frames is the
michael@0 34 // enclosing function. BaselineFrame::evalScript_ stores the eval script
michael@0 35 // itself.
michael@0 36 class BaselineFrame
michael@0 37 {
michael@0 38 public:
michael@0 39 enum Flags {
michael@0 40 // The frame has a valid return value. See also InterpreterFrame::HAS_RVAL.
michael@0 41 HAS_RVAL = 1 << 0,
michael@0 42
michael@0 43 // A call object has been pushed on the scope chain.
michael@0 44 HAS_CALL_OBJ = 1 << 2,
michael@0 45
michael@0 46 // Frame has an arguments object, argsObj_.
michael@0 47 HAS_ARGS_OBJ = 1 << 4,
michael@0 48
michael@0 49 // See InterpreterFrame::PREV_UP_TO_DATE.
michael@0 50 PREV_UP_TO_DATE = 1 << 5,
michael@0 51
michael@0 52 // Eval frame, see the "eval frames" comment.
michael@0 53 EVAL = 1 << 6,
michael@0 54
michael@0 55 // Frame has hookData_ set.
michael@0 56 HAS_HOOK_DATA = 1 << 7,
michael@0 57
michael@0 58 // Frame has profiler entry pushed.
michael@0 59 HAS_PUSHED_SPS_FRAME = 1 << 8,
michael@0 60
michael@0 61 // Frame has over-recursed on an early check.
michael@0 62 OVER_RECURSED = 1 << 9,
michael@0 63
michael@0 64 // Frame has a BaselineRecompileInfo stashed in the scratch value
michael@0 65 // slot. See PatchBaselineFramesForDebugMOde.
michael@0 66 HAS_DEBUG_MODE_OSR_INFO = 1 << 10
michael@0 67 };
michael@0 68
michael@0 69 protected: // Silence Clang warning about unused private fields.
michael@0 70 // We need to split the Value into 2 fields of 32 bits, otherwise the C++
michael@0 71 // compiler may add some padding between the fields.
michael@0 72 uint32_t loScratchValue_;
michael@0 73 uint32_t hiScratchValue_;
michael@0 74 uint32_t loReturnValue_; // If HAS_RVAL, the frame's return value.
michael@0 75 uint32_t hiReturnValue_;
michael@0 76 uint32_t frameSize_;
michael@0 77 JSObject *scopeChain_; // Scope chain (always initialized).
michael@0 78 JSScript *evalScript_; // If isEvalFrame(), the current eval script.
michael@0 79 ArgumentsObject *argsObj_; // If HAS_ARGS_OBJ, the arguments object.
michael@0 80 void *hookData_; // If HAS_HOOK_DATA, debugger call hook data.
michael@0 81 uint32_t flags_;
michael@0 82 #if JS_BITS_PER_WORD == 32
michael@0 83 uint32_t padding_; // Pad to 8-byte alignment.
michael@0 84 #endif
michael@0 85
michael@0 86 public:
michael@0 87 // Distance between the frame pointer and the frame header (return address).
michael@0 88 // This is the old frame pointer saved in the prologue.
michael@0 89 static const uint32_t FramePointerOffset = sizeof(void *);
michael@0 90
michael@0 91 bool initForOsr(InterpreterFrame *fp, uint32_t numStackValues);
michael@0 92
michael@0 93 uint32_t frameSize() const {
michael@0 94 return frameSize_;
michael@0 95 }
michael@0 96 void setFrameSize(uint32_t frameSize) {
michael@0 97 frameSize_ = frameSize;
michael@0 98 }
michael@0 99 inline uint32_t *addressOfFrameSize() {
michael@0 100 return &frameSize_;
michael@0 101 }
michael@0 102 JSObject *scopeChain() const {
michael@0 103 return scopeChain_;
michael@0 104 }
michael@0 105 void setScopeChain(JSObject *scopeChain) {
michael@0 106 scopeChain_ = scopeChain;
michael@0 107 }
michael@0 108 inline JSObject **addressOfScopeChain() {
michael@0 109 return &scopeChain_;
michael@0 110 }
michael@0 111
michael@0 112 inline Value *addressOfScratchValue() {
michael@0 113 return reinterpret_cast<Value *>(&loScratchValue_);
michael@0 114 }
michael@0 115
michael@0 116 inline void pushOnScopeChain(ScopeObject &scope);
michael@0 117 inline void popOffScopeChain();
michael@0 118
michael@0 119 inline void popWith(JSContext *cx);
michael@0 120
michael@0 121 CalleeToken calleeToken() const {
michael@0 122 uint8_t *pointer = (uint8_t *)this + Size() + offsetOfCalleeToken();
michael@0 123 return *(CalleeToken *)pointer;
michael@0 124 }
michael@0 125 void replaceCalleeToken(CalleeToken token) {
michael@0 126 uint8_t *pointer = (uint8_t *)this + Size() + offsetOfCalleeToken();
michael@0 127 *(CalleeToken *)pointer = token;
michael@0 128 }
michael@0 129 JSScript *script() const {
michael@0 130 if (isEvalFrame())
michael@0 131 return evalScript();
michael@0 132 return ScriptFromCalleeToken(calleeToken());
michael@0 133 }
michael@0 134 JSFunction *fun() const {
michael@0 135 return CalleeTokenToFunction(calleeToken());
michael@0 136 }
michael@0 137 JSFunction *maybeFun() const {
michael@0 138 return isFunctionFrame() ? fun() : nullptr;
michael@0 139 }
michael@0 140 JSFunction *callee() const {
michael@0 141 return CalleeTokenToFunction(calleeToken());
michael@0 142 }
michael@0 143 Value calleev() const {
michael@0 144 return ObjectValue(*callee());
michael@0 145 }
michael@0 146 size_t numValueSlots() const {
michael@0 147 size_t size = frameSize();
michael@0 148
michael@0 149 JS_ASSERT(size >= BaselineFrame::FramePointerOffset + BaselineFrame::Size());
michael@0 150 size -= BaselineFrame::FramePointerOffset + BaselineFrame::Size();
michael@0 151
michael@0 152 JS_ASSERT((size % sizeof(Value)) == 0);
michael@0 153 return size / sizeof(Value);
michael@0 154 }
michael@0 155 Value *valueSlot(size_t slot) const {
michael@0 156 JS_ASSERT(slot < numValueSlots());
michael@0 157 return (Value *)this - (slot + 1);
michael@0 158 }
michael@0 159
michael@0 160 Value &unaliasedVar(uint32_t i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
michael@0 161 JS_ASSERT(i < script()->nfixedvars());
michael@0 162 JS_ASSERT_IF(checkAliasing, !script()->varIsAliased(i));
michael@0 163 return *valueSlot(i);
michael@0 164 }
michael@0 165
michael@0 166 Value &unaliasedFormal(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
michael@0 167 JS_ASSERT(i < numFormalArgs());
michael@0 168 JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals() &&
michael@0 169 !script()->formalIsAliased(i));
michael@0 170 return argv()[i];
michael@0 171 }
michael@0 172
michael@0 173 Value &unaliasedActual(unsigned i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
michael@0 174 JS_ASSERT(i < numActualArgs());
michael@0 175 JS_ASSERT_IF(checkAliasing, !script()->argsObjAliasesFormals());
michael@0 176 JS_ASSERT_IF(checkAliasing && i < numFormalArgs(), !script()->formalIsAliased(i));
michael@0 177 return argv()[i];
michael@0 178 }
michael@0 179
michael@0 180 Value &unaliasedLocal(uint32_t i, MaybeCheckAliasing checkAliasing = CHECK_ALIASING) const {
michael@0 181 JS_ASSERT(i < script()->nfixed());
michael@0 182 #ifdef DEBUG
michael@0 183 CheckLocalUnaliased(checkAliasing, script(), i);
michael@0 184 #endif
michael@0 185 return *valueSlot(i);
michael@0 186 }
michael@0 187
michael@0 188 unsigned numActualArgs() const {
michael@0 189 return *(size_t *)(reinterpret_cast<const uint8_t *>(this) +
michael@0 190 BaselineFrame::Size() +
michael@0 191 offsetOfNumActualArgs());
michael@0 192 }
michael@0 193 unsigned numFormalArgs() const {
michael@0 194 return script()->functionNonDelazifying()->nargs();
michael@0 195 }
michael@0 196 Value &thisValue() const {
michael@0 197 return *(Value *)(reinterpret_cast<const uint8_t *>(this) +
michael@0 198 BaselineFrame::Size() +
michael@0 199 offsetOfThis());
michael@0 200 }
michael@0 201 Value *argv() const {
michael@0 202 return (Value *)(reinterpret_cast<const uint8_t *>(this) +
michael@0 203 BaselineFrame::Size() +
michael@0 204 offsetOfArg(0));
michael@0 205 }
michael@0 206
michael@0 207 bool copyRawFrameSlots(AutoValueVector *vec) const;
michael@0 208
michael@0 209 bool hasReturnValue() const {
michael@0 210 return flags_ & HAS_RVAL;
michael@0 211 }
michael@0 212 MutableHandleValue returnValue() {
michael@0 213 return MutableHandleValue::fromMarkedLocation(reinterpret_cast<Value *>(&loReturnValue_));
michael@0 214 }
michael@0 215 void setReturnValue(const Value &v) {
michael@0 216 flags_ |= HAS_RVAL;
michael@0 217 returnValue().set(v);
michael@0 218 }
michael@0 219 inline Value *addressOfReturnValue() {
michael@0 220 return reinterpret_cast<Value *>(&loReturnValue_);
michael@0 221 }
michael@0 222
michael@0 223 bool hasCallObj() const {
michael@0 224 return flags_ & HAS_CALL_OBJ;
michael@0 225 }
michael@0 226
michael@0 227 inline CallObject &callObj() const;
michael@0 228
michael@0 229 void setFlags(uint32_t flags) {
michael@0 230 flags_ = flags;
michael@0 231 }
michael@0 232 uint32_t *addressOfFlags() {
michael@0 233 return &flags_;
michael@0 234 }
michael@0 235
michael@0 236 inline bool pushBlock(JSContext *cx, Handle<StaticBlockObject *> block);
michael@0 237 inline void popBlock(JSContext *cx);
michael@0 238
michael@0 239 bool strictEvalPrologue(JSContext *cx);
michael@0 240 bool heavyweightFunPrologue(JSContext *cx);
michael@0 241 bool initFunctionScopeObjects(JSContext *cx);
michael@0 242
michael@0 243 void initArgsObjUnchecked(ArgumentsObject &argsobj) {
michael@0 244 flags_ |= HAS_ARGS_OBJ;
michael@0 245 argsObj_ = &argsobj;
michael@0 246 }
michael@0 247 void initArgsObj(ArgumentsObject &argsobj) {
michael@0 248 JS_ASSERT(script()->needsArgsObj());
michael@0 249 initArgsObjUnchecked(argsobj);
michael@0 250 }
michael@0 251 bool hasArgsObj() const {
michael@0 252 return flags_ & HAS_ARGS_OBJ;
michael@0 253 }
michael@0 254 ArgumentsObject &argsObj() const {
michael@0 255 JS_ASSERT(hasArgsObj());
michael@0 256 JS_ASSERT(script()->needsArgsObj());
michael@0 257 return *argsObj_;
michael@0 258 }
michael@0 259
michael@0 260 bool prevUpToDate() const {
michael@0 261 return flags_ & PREV_UP_TO_DATE;
michael@0 262 }
michael@0 263 void setPrevUpToDate() {
michael@0 264 flags_ |= PREV_UP_TO_DATE;
michael@0 265 }
michael@0 266
michael@0 267 JSScript *evalScript() const {
michael@0 268 JS_ASSERT(isEvalFrame());
michael@0 269 return evalScript_;
michael@0 270 }
michael@0 271
michael@0 272 bool hasHookData() const {
michael@0 273 return flags_ & HAS_HOOK_DATA;
michael@0 274 }
michael@0 275
michael@0 276 void *maybeHookData() const {
michael@0 277 return hasHookData() ? hookData_ : nullptr;
michael@0 278 }
michael@0 279
michael@0 280 void setHookData(void *v) {
michael@0 281 hookData_ = v;
michael@0 282 flags_ |= HAS_HOOK_DATA;
michael@0 283 }
michael@0 284
michael@0 285 bool hasPushedSPSFrame() const {
michael@0 286 return flags_ & HAS_PUSHED_SPS_FRAME;
michael@0 287 }
michael@0 288
michael@0 289 void setPushedSPSFrame() {
michael@0 290 flags_ |= HAS_PUSHED_SPS_FRAME;
michael@0 291 }
michael@0 292
michael@0 293 void unsetPushedSPSFrame() {
michael@0 294 flags_ &= ~HAS_PUSHED_SPS_FRAME;
michael@0 295 }
michael@0 296
michael@0 297 bool overRecursed() const {
michael@0 298 return flags_ & OVER_RECURSED;
michael@0 299 }
michael@0 300
michael@0 301 void setOverRecursed() {
michael@0 302 flags_ |= OVER_RECURSED;
michael@0 303 }
michael@0 304
michael@0 305 BaselineDebugModeOSRInfo *debugModeOSRInfo() {
michael@0 306 MOZ_ASSERT(flags_ & HAS_DEBUG_MODE_OSR_INFO);
michael@0 307 return *reinterpret_cast<BaselineDebugModeOSRInfo **>(&loScratchValue_);
michael@0 308 }
michael@0 309
michael@0 310 BaselineDebugModeOSRInfo *getDebugModeOSRInfo() {
michael@0 311 if (flags_ & HAS_DEBUG_MODE_OSR_INFO)
michael@0 312 return debugModeOSRInfo();
michael@0 313 return nullptr;
michael@0 314 }
michael@0 315
michael@0 316 void setDebugModeOSRInfo(BaselineDebugModeOSRInfo *info) {
michael@0 317 flags_ |= HAS_DEBUG_MODE_OSR_INFO;
michael@0 318 *reinterpret_cast<BaselineDebugModeOSRInfo **>(&loScratchValue_) = info;
michael@0 319 }
michael@0 320
michael@0 321 void deleteDebugModeOSRInfo();
michael@0 322
michael@0 323 void trace(JSTracer *trc, JitFrameIterator &frame);
michael@0 324
michael@0 325 bool isFunctionFrame() const {
michael@0 326 return CalleeTokenIsFunction(calleeToken());
michael@0 327 }
michael@0 328 bool isGlobalFrame() const {
michael@0 329 return !CalleeTokenIsFunction(calleeToken());
michael@0 330 }
michael@0 331 bool isEvalFrame() const {
michael@0 332 return flags_ & EVAL;
michael@0 333 }
michael@0 334 bool isStrictEvalFrame() const {
michael@0 335 return isEvalFrame() && script()->strict();
michael@0 336 }
michael@0 337 bool isNonStrictEvalFrame() const {
michael@0 338 return isEvalFrame() && !script()->strict();
michael@0 339 }
michael@0 340 bool isDirectEvalFrame() const {
michael@0 341 return isEvalFrame() && script()->staticLevel() > 0;
michael@0 342 }
michael@0 343 bool isNonStrictDirectEvalFrame() const {
michael@0 344 return isNonStrictEvalFrame() && isDirectEvalFrame();
michael@0 345 }
michael@0 346 bool isNonEvalFunctionFrame() const {
michael@0 347 return isFunctionFrame() && !isEvalFrame();
michael@0 348 }
michael@0 349 bool isDebuggerFrame() const {
michael@0 350 return false;
michael@0 351 }
michael@0 352 bool isGeneratorFrame() const {
michael@0 353 return false;
michael@0 354 }
michael@0 355
michael@0 356 IonJSFrameLayout *framePrefix() const {
michael@0 357 uint8_t *fp = (uint8_t *)this + Size() + FramePointerOffset;
michael@0 358 return (IonJSFrameLayout *)fp;
michael@0 359 }
michael@0 360
michael@0 361 // Methods below are used by the compiler.
michael@0 362 static size_t offsetOfCalleeToken() {
michael@0 363 return FramePointerOffset + js::jit::IonJSFrameLayout::offsetOfCalleeToken();
michael@0 364 }
michael@0 365 static size_t offsetOfThis() {
michael@0 366 return FramePointerOffset + js::jit::IonJSFrameLayout::offsetOfThis();
michael@0 367 }
michael@0 368 static size_t offsetOfArg(size_t index) {
michael@0 369 return FramePointerOffset + js::jit::IonJSFrameLayout::offsetOfActualArg(index);
michael@0 370 }
michael@0 371 static size_t offsetOfNumActualArgs() {
michael@0 372 return FramePointerOffset + js::jit::IonJSFrameLayout::offsetOfNumActualArgs();
michael@0 373 }
michael@0 374 static size_t Size() {
michael@0 375 return sizeof(BaselineFrame);
michael@0 376 }
michael@0 377
michael@0 378 // The reverseOffsetOf methods below compute the offset relative to the
michael@0 379 // frame's base pointer. Since the stack grows down, these offsets are
michael@0 380 // negative.
michael@0 381 static int reverseOffsetOfFrameSize() {
michael@0 382 return -int(Size()) + offsetof(BaselineFrame, frameSize_);
michael@0 383 }
michael@0 384 static int reverseOffsetOfScratchValue() {
michael@0 385 return -int(Size()) + offsetof(BaselineFrame, loScratchValue_);
michael@0 386 }
michael@0 387 static int reverseOffsetOfScopeChain() {
michael@0 388 return -int(Size()) + offsetof(BaselineFrame, scopeChain_);
michael@0 389 }
michael@0 390 static int reverseOffsetOfArgsObj() {
michael@0 391 return -int(Size()) + offsetof(BaselineFrame, argsObj_);
michael@0 392 }
michael@0 393 static int reverseOffsetOfFlags() {
michael@0 394 return -int(Size()) + offsetof(BaselineFrame, flags_);
michael@0 395 }
michael@0 396 static int reverseOffsetOfEvalScript() {
michael@0 397 return -int(Size()) + offsetof(BaselineFrame, evalScript_);
michael@0 398 }
michael@0 399 static int reverseOffsetOfReturnValue() {
michael@0 400 return -int(Size()) + offsetof(BaselineFrame, loReturnValue_);
michael@0 401 }
michael@0 402 static int reverseOffsetOfLocal(size_t index) {
michael@0 403 return -int(Size()) - (index + 1) * sizeof(Value);
michael@0 404 }
michael@0 405 };
michael@0 406
michael@0 407 // Ensure the frame is 8-byte aligned (required on ARM).
michael@0 408 JS_STATIC_ASSERT(((sizeof(BaselineFrame) + BaselineFrame::FramePointerOffset) % 8) == 0);
michael@0 409
michael@0 410 } // namespace jit
michael@0 411 } // namespace js
michael@0 412
michael@0 413 #endif // JS_ION
michael@0 414
michael@0 415 #endif /* jit_BaselineFrame_h */

mercurial