js/src/jit/BaselineFrame.cpp

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 #include "jit/BaselineFrame-inl.h"
michael@0 8
michael@0 9 #include "jit/BaselineJIT.h"
michael@0 10 #include "jit/Ion.h"
michael@0 11 #include "vm/Debugger.h"
michael@0 12 #include "vm/ScopeObject.h"
michael@0 13
michael@0 14 #include "jit/IonFrames-inl.h"
michael@0 15 #include "vm/Stack-inl.h"
michael@0 16
michael@0 17 using namespace js;
michael@0 18 using namespace js::jit;
michael@0 19
michael@0 20 static void
michael@0 21 MarkLocals(BaselineFrame *frame, JSTracer *trc, unsigned start, unsigned end)
michael@0 22 {
michael@0 23 if (start < end) {
michael@0 24 // Stack grows down.
michael@0 25 Value *last = frame->valueSlot(end - 1);
michael@0 26 gc::MarkValueRootRange(trc, end - start, last, "baseline-stack");
michael@0 27 }
michael@0 28 }
michael@0 29
michael@0 30 void
michael@0 31 BaselineFrame::trace(JSTracer *trc, JitFrameIterator &frameIterator)
michael@0 32 {
michael@0 33 replaceCalleeToken(MarkCalleeToken(trc, calleeToken()));
michael@0 34
michael@0 35 gc::MarkValueRoot(trc, &thisValue(), "baseline-this");
michael@0 36
michael@0 37 // Mark actual and formal args.
michael@0 38 if (isNonEvalFunctionFrame()) {
michael@0 39 unsigned numArgs = js::Max(numActualArgs(), numFormalArgs());
michael@0 40 gc::MarkValueRootRange(trc, numArgs, argv(), "baseline-args");
michael@0 41 }
michael@0 42
michael@0 43 // Mark scope chain, if it exists.
michael@0 44 if (scopeChain_)
michael@0 45 gc::MarkObjectRoot(trc, &scopeChain_, "baseline-scopechain");
michael@0 46
michael@0 47 // Mark return value.
michael@0 48 if (hasReturnValue())
michael@0 49 gc::MarkValueRoot(trc, returnValue().address(), "baseline-rval");
michael@0 50
michael@0 51 if (isEvalFrame())
michael@0 52 gc::MarkScriptRoot(trc, &evalScript_, "baseline-evalscript");
michael@0 53
michael@0 54 if (hasArgsObj())
michael@0 55 gc::MarkObjectRoot(trc, &argsObj_, "baseline-args-obj");
michael@0 56
michael@0 57 // Mark locals and stack values.
michael@0 58 JSScript *script = this->script();
michael@0 59 size_t nfixed = script->nfixed();
michael@0 60 size_t nlivefixed = script->nfixedvars();
michael@0 61
michael@0 62 if (nfixed != nlivefixed) {
michael@0 63 jsbytecode *pc;
michael@0 64 NestedScopeObject *staticScope;
michael@0 65
michael@0 66 frameIterator.baselineScriptAndPc(nullptr, &pc);
michael@0 67 staticScope = script->getStaticScope(pc);
michael@0 68 while (staticScope && !staticScope->is<StaticBlockObject>())
michael@0 69 staticScope = staticScope->enclosingNestedScope();
michael@0 70
michael@0 71 if (staticScope) {
michael@0 72 StaticBlockObject &blockObj = staticScope->as<StaticBlockObject>();
michael@0 73 nlivefixed = blockObj.localOffset() + blockObj.numVariables();
michael@0 74 }
michael@0 75 }
michael@0 76
michael@0 77 JS_ASSERT(nlivefixed <= nfixed);
michael@0 78 JS_ASSERT(nlivefixed >= script->nfixedvars());
michael@0 79
michael@0 80 // NB: It is possible that numValueSlots() could be zero, even if nfixed is
michael@0 81 // nonzero. This is the case if the function has an early stack check.
michael@0 82 if (numValueSlots() == 0)
michael@0 83 return;
michael@0 84
michael@0 85 JS_ASSERT(nfixed <= numValueSlots());
michael@0 86
michael@0 87 if (nfixed == nlivefixed) {
michael@0 88 // All locals are live.
michael@0 89 MarkLocals(this, trc, 0, numValueSlots());
michael@0 90 } else {
michael@0 91 // Mark operand stack.
michael@0 92 MarkLocals(this, trc, nfixed, numValueSlots());
michael@0 93
michael@0 94 // Clear dead locals.
michael@0 95 while (nfixed > nlivefixed)
michael@0 96 unaliasedLocal(--nfixed, DONT_CHECK_ALIASING).setUndefined();
michael@0 97
michael@0 98 // Mark live locals.
michael@0 99 MarkLocals(this, trc, 0, nlivefixed);
michael@0 100 }
michael@0 101 }
michael@0 102
michael@0 103 bool
michael@0 104 BaselineFrame::copyRawFrameSlots(AutoValueVector *vec) const
michael@0 105 {
michael@0 106 unsigned nfixed = script()->nfixed();
michael@0 107 unsigned nformals = numFormalArgs();
michael@0 108
michael@0 109 if (!vec->resize(nformals + nfixed))
michael@0 110 return false;
michael@0 111
michael@0 112 mozilla::PodCopy(vec->begin(), argv(), nformals);
michael@0 113 for (unsigned i = 0; i < nfixed; i++)
michael@0 114 (*vec)[nformals + i] = *valueSlot(i);
michael@0 115 return true;
michael@0 116 }
michael@0 117
michael@0 118 bool
michael@0 119 BaselineFrame::strictEvalPrologue(JSContext *cx)
michael@0 120 {
michael@0 121 JS_ASSERT(isStrictEvalFrame());
michael@0 122
michael@0 123 CallObject *callobj = CallObject::createForStrictEval(cx, this);
michael@0 124 if (!callobj)
michael@0 125 return false;
michael@0 126
michael@0 127 pushOnScopeChain(*callobj);
michael@0 128 flags_ |= HAS_CALL_OBJ;
michael@0 129 return true;
michael@0 130 }
michael@0 131
michael@0 132 bool
michael@0 133 BaselineFrame::heavyweightFunPrologue(JSContext *cx)
michael@0 134 {
michael@0 135 return initFunctionScopeObjects(cx);
michael@0 136 }
michael@0 137
michael@0 138 bool
michael@0 139 BaselineFrame::initFunctionScopeObjects(JSContext *cx)
michael@0 140 {
michael@0 141 JS_ASSERT(isNonEvalFunctionFrame());
michael@0 142 JS_ASSERT(fun()->isHeavyweight());
michael@0 143
michael@0 144 CallObject *callobj = CallObject::createForFunction(cx, this);
michael@0 145 if (!callobj)
michael@0 146 return false;
michael@0 147
michael@0 148 pushOnScopeChain(*callobj);
michael@0 149 flags_ |= HAS_CALL_OBJ;
michael@0 150 return true;
michael@0 151 }
michael@0 152
michael@0 153 bool
michael@0 154 BaselineFrame::initForOsr(InterpreterFrame *fp, uint32_t numStackValues)
michael@0 155 {
michael@0 156 mozilla::PodZero(this);
michael@0 157
michael@0 158 scopeChain_ = fp->scopeChain();
michael@0 159
michael@0 160 if (fp->hasCallObjUnchecked())
michael@0 161 flags_ |= BaselineFrame::HAS_CALL_OBJ;
michael@0 162
michael@0 163 if (fp->isEvalFrame()) {
michael@0 164 flags_ |= BaselineFrame::EVAL;
michael@0 165 evalScript_ = fp->script();
michael@0 166 }
michael@0 167
michael@0 168 if (fp->script()->needsArgsObj() && fp->hasArgsObj()) {
michael@0 169 flags_ |= BaselineFrame::HAS_ARGS_OBJ;
michael@0 170 argsObj_ = &fp->argsObj();
michael@0 171 }
michael@0 172
michael@0 173 if (fp->hasHookData()) {
michael@0 174 flags_ |= BaselineFrame::HAS_HOOK_DATA;
michael@0 175 hookData_ = fp->hookData();
michael@0 176 }
michael@0 177
michael@0 178 if (fp->hasReturnValue())
michael@0 179 setReturnValue(fp->returnValue());
michael@0 180
michael@0 181 // If the interpreter pushed an SPS frame when it entered the function, the
michael@0 182 // interpreter will pop it after the OSR trampoline returns. In order for
michael@0 183 // the Baseline frame to have its SPS flag set, it must have its own SPS
michael@0 184 // frame, which the Baseline code will pop on return. Note that the
michael@0 185 // profiler may have been enabled or disabled after the function was entered
michael@0 186 // but before OSR.
michael@0 187 JSContext *cx = GetJSContextFromJitCode();
michael@0 188 SPSProfiler *p = &(cx->runtime()->spsProfiler);
michael@0 189 if (p->enabled()) {
michael@0 190 p->enter(fp->script(), fp->maybeFun());
michael@0 191 flags_ |= BaselineFrame::HAS_PUSHED_SPS_FRAME;
michael@0 192 }
michael@0 193
michael@0 194 frameSize_ = BaselineFrame::FramePointerOffset +
michael@0 195 BaselineFrame::Size() +
michael@0 196 numStackValues * sizeof(Value);
michael@0 197
michael@0 198 JS_ASSERT(numValueSlots() == numStackValues);
michael@0 199
michael@0 200 for (uint32_t i = 0; i < numStackValues; i++)
michael@0 201 *valueSlot(i) = fp->slots()[i];
michael@0 202
michael@0 203 if (cx->compartment()->debugMode()) {
michael@0 204 // In debug mode, update any Debugger.Frame objects for the
michael@0 205 // InterpreterFrame to point to the BaselineFrame.
michael@0 206
michael@0 207 // The caller pushed a fake return address. ScriptFrameIter, used by the
michael@0 208 // debugger, wants a valid return address, but it's okay to just pick one.
michael@0 209 // In debug mode there's always at least 1 ICEntry (since there are always
michael@0 210 // debug prologue/epilogue calls).
michael@0 211 JitFrameIterator iter(cx);
michael@0 212 JS_ASSERT(iter.returnAddress() == nullptr);
michael@0 213 BaselineScript *baseline = fp->script()->baselineScript();
michael@0 214 iter.current()->setReturnAddress(baseline->returnAddressForIC(baseline->icEntry(0)));
michael@0 215
michael@0 216 if (!Debugger::handleBaselineOsr(cx, fp, this))
michael@0 217 return false;
michael@0 218 }
michael@0 219
michael@0 220 return true;
michael@0 221 }

mercurial