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