js/src/jit/BaselineJIT.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_BaselineJIT_h
michael@0 8 #define jit_BaselineJIT_h
michael@0 9
michael@0 10 #ifdef JS_ION
michael@0 11
michael@0 12 #include "mozilla/MemoryReporting.h"
michael@0 13
michael@0 14 #include "jscntxt.h"
michael@0 15 #include "jscompartment.h"
michael@0 16
michael@0 17 #include "ds/LifoAlloc.h"
michael@0 18 #include "jit/Bailouts.h"
michael@0 19 #include "jit/IonCode.h"
michael@0 20 #include "jit/IonMacroAssembler.h"
michael@0 21
michael@0 22 namespace js {
michael@0 23 namespace jit {
michael@0 24
michael@0 25 class StackValue;
michael@0 26 class ICEntry;
michael@0 27 class ICStub;
michael@0 28
michael@0 29 class PCMappingSlotInfo
michael@0 30 {
michael@0 31 uint8_t slotInfo_;
michael@0 32
michael@0 33 public:
michael@0 34 // SlotInfo encoding:
michael@0 35 // Bits 0 & 1: number of slots at top of stack which are unsynced.
michael@0 36 // Bits 2 & 3: SlotLocation of top slot value (only relevant if numUnsynced > 0).
michael@0 37 // Bits 3 & 4: SlotLocation of next slot value (only relevant if numUnsynced > 1).
michael@0 38 enum SlotLocation { SlotInR0 = 0, SlotInR1 = 1, SlotIgnore = 3 };
michael@0 39
michael@0 40 PCMappingSlotInfo()
michael@0 41 : slotInfo_(0)
michael@0 42 { }
michael@0 43
michael@0 44 explicit PCMappingSlotInfo(uint8_t slotInfo)
michael@0 45 : slotInfo_(slotInfo)
michael@0 46 { }
michael@0 47
michael@0 48 static inline bool ValidSlotLocation(SlotLocation loc) {
michael@0 49 return (loc == SlotInR0) || (loc == SlotInR1) || (loc == SlotIgnore);
michael@0 50 }
michael@0 51
michael@0 52 static SlotLocation ToSlotLocation(const StackValue *stackVal);
michael@0 53
michael@0 54 inline static PCMappingSlotInfo MakeSlotInfo() { return PCMappingSlotInfo(0); }
michael@0 55
michael@0 56 inline static PCMappingSlotInfo MakeSlotInfo(SlotLocation topSlotLoc) {
michael@0 57 JS_ASSERT(ValidSlotLocation(topSlotLoc));
michael@0 58 return PCMappingSlotInfo(1 | (topSlotLoc << 2));
michael@0 59 }
michael@0 60
michael@0 61 inline static PCMappingSlotInfo MakeSlotInfo(SlotLocation topSlotLoc, SlotLocation nextSlotLoc) {
michael@0 62 JS_ASSERT(ValidSlotLocation(topSlotLoc));
michael@0 63 JS_ASSERT(ValidSlotLocation(nextSlotLoc));
michael@0 64 return PCMappingSlotInfo(2 | (topSlotLoc << 2) | (nextSlotLoc) << 4);
michael@0 65 }
michael@0 66
michael@0 67 inline unsigned numUnsynced() const {
michael@0 68 return slotInfo_ & 0x3;
michael@0 69 }
michael@0 70 inline SlotLocation topSlotLocation() const {
michael@0 71 return static_cast<SlotLocation>((slotInfo_ >> 2) & 0x3);
michael@0 72 }
michael@0 73 inline SlotLocation nextSlotLocation() const {
michael@0 74 return static_cast<SlotLocation>((slotInfo_ >> 4) & 0x3);
michael@0 75 }
michael@0 76 inline uint8_t toByte() const {
michael@0 77 return slotInfo_;
michael@0 78 }
michael@0 79 };
michael@0 80
michael@0 81 // A CompactBuffer is used to store native code offsets (relative to the
michael@0 82 // previous pc) and PCMappingSlotInfo bytes. To allow binary search into this
michael@0 83 // table, we maintain a second table of "index" entries. Every X ops, the
michael@0 84 // compiler will add an index entry, so that from the index entry to the
michael@0 85 // actual native code offset, we have to iterate at most X times.
michael@0 86 struct PCMappingIndexEntry
michael@0 87 {
michael@0 88 // jsbytecode offset.
michael@0 89 uint32_t pcOffset;
michael@0 90
michael@0 91 // Native code offset.
michael@0 92 uint32_t nativeOffset;
michael@0 93
michael@0 94 // Offset in the CompactBuffer where data for pcOffset starts.
michael@0 95 uint32_t bufferOffset;
michael@0 96 };
michael@0 97
michael@0 98 struct BaselineScript
michael@0 99 {
michael@0 100 public:
michael@0 101 static const uint32_t MAX_JSSCRIPT_LENGTH = 0x0fffffffu;
michael@0 102
michael@0 103 // Limit the locals on a given script so that stack check on baseline frames
michael@0 104 // doesn't overflow a uint32_t value.
michael@0 105 // (MAX_JSSCRIPT_SLOTS * sizeof(Value)) must fit within a uint32_t.
michael@0 106 static const uint32_t MAX_JSSCRIPT_SLOTS = 0xffffu;
michael@0 107
michael@0 108 private:
michael@0 109 // Code pointer containing the actual method.
michael@0 110 HeapPtr<JitCode> method_;
michael@0 111
michael@0 112 // For heavyweight scripts, template objects to use for the call object and
michael@0 113 // decl env object (linked via the call object's enclosing scope).
michael@0 114 HeapPtrObject templateScope_;
michael@0 115
michael@0 116 // Allocated space for fallback stubs.
michael@0 117 FallbackICStubSpace fallbackStubSpace_;
michael@0 118
michael@0 119 // Native code offset right before the scope chain is initialized.
michael@0 120 uint32_t prologueOffset_;
michael@0 121
michael@0 122 // Native code offset right before the frame is popped and the method
michael@0 123 // returned from.
michael@0 124 uint32_t epilogueOffset_;
michael@0 125
michael@0 126 // The offsets for the toggledJump instructions for SPS update ICs.
michael@0 127 #ifdef DEBUG
michael@0 128 mozilla::DebugOnly<bool> spsOn_;
michael@0 129 #endif
michael@0 130 uint32_t spsPushToggleOffset_;
michael@0 131
michael@0 132 // Native code offsets right after the debug prologue VM call returns, or
michael@0 133 // would have returned. This offset is recorded even when debug mode is
michael@0 134 // off to aid on-stack debug mode recompilation.
michael@0 135 //
michael@0 136 // We don't need one for the debug epilogue because that always happens
michael@0 137 // right before the epilogue, so we just use the epilogue offset.
michael@0 138 uint32_t postDebugPrologueOffset_;
michael@0 139
michael@0 140 public:
michael@0 141 enum Flag {
michael@0 142 // Flag set by JSScript::argumentsOptimizationFailed. Similar to
michael@0 143 // JSScript::needsArgsObj_, but can be read from JIT code.
michael@0 144 NEEDS_ARGS_OBJ = 1 << 0,
michael@0 145
michael@0 146 // Flag set when discarding JIT code, to indicate this script is
michael@0 147 // on the stack and should not be discarded.
michael@0 148 ACTIVE = 1 << 1,
michael@0 149
michael@0 150 // Flag set when the script contains any writes to its on-stack
michael@0 151 // (rather than call object stored) arguments.
michael@0 152 MODIFIES_ARGUMENTS = 1 << 2,
michael@0 153
michael@0 154 // Flag set when compiled for use for debug mode. Handles various
michael@0 155 // Debugger hooks and compiles toggled calls for traps.
michael@0 156 DEBUG_MODE = 1 << 3
michael@0 157 };
michael@0 158
michael@0 159 private:
michael@0 160 uint32_t flags_;
michael@0 161
michael@0 162 private:
michael@0 163 void trace(JSTracer *trc);
michael@0 164
michael@0 165 uint32_t icEntriesOffset_;
michael@0 166 uint32_t icEntries_;
michael@0 167
michael@0 168 uint32_t pcMappingIndexOffset_;
michael@0 169 uint32_t pcMappingIndexEntries_;
michael@0 170
michael@0 171 uint32_t pcMappingOffset_;
michael@0 172 uint32_t pcMappingSize_;
michael@0 173
michael@0 174 // List mapping indexes of bytecode type sets to the offset of the opcode
michael@0 175 // they correspond to, for use by TypeScript::BytecodeTypes.
michael@0 176 uint32_t bytecodeTypeMapOffset_;
michael@0 177
michael@0 178 public:
michael@0 179 // Do not call directly, use BaselineScript::New. This is public for cx->new_.
michael@0 180 BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
michael@0 181 uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset);
michael@0 182
michael@0 183 static BaselineScript *New(JSContext *cx, uint32_t prologueOffset,
michael@0 184 uint32_t epilogueOffset, uint32_t postDebugPrologueOffset,
michael@0 185 uint32_t spsPushToggleOffset, size_t icEntries,
michael@0 186 size_t pcMappingIndexEntries, size_t pcMappingSize,
michael@0 187 size_t bytecodeTypeMapEntries);
michael@0 188 static void Trace(JSTracer *trc, BaselineScript *script);
michael@0 189 static void Destroy(FreeOp *fop, BaselineScript *script);
michael@0 190
michael@0 191 void purgeOptimizedStubs(Zone *zone);
michael@0 192
michael@0 193 static inline size_t offsetOfMethod() {
michael@0 194 return offsetof(BaselineScript, method_);
michael@0 195 }
michael@0 196
michael@0 197 void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t *data,
michael@0 198 size_t *fallbackStubs) const {
michael@0 199 *data += mallocSizeOf(this);
michael@0 200
michael@0 201 // |data| already includes the ICStubSpace itself, so use
michael@0 202 // sizeOfExcludingThis.
michael@0 203 *fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
michael@0 204 }
michael@0 205
michael@0 206 bool active() const {
michael@0 207 return flags_ & ACTIVE;
michael@0 208 }
michael@0 209 void setActive() {
michael@0 210 flags_ |= ACTIVE;
michael@0 211 }
michael@0 212 void resetActive() {
michael@0 213 flags_ &= ~ACTIVE;
michael@0 214 }
michael@0 215
michael@0 216 void setNeedsArgsObj() {
michael@0 217 flags_ |= NEEDS_ARGS_OBJ;
michael@0 218 }
michael@0 219
michael@0 220 void setModifiesArguments() {
michael@0 221 flags_ |= MODIFIES_ARGUMENTS;
michael@0 222 }
michael@0 223 bool modifiesArguments() {
michael@0 224 return flags_ & MODIFIES_ARGUMENTS;
michael@0 225 }
michael@0 226
michael@0 227 void setDebugMode() {
michael@0 228 flags_ |= DEBUG_MODE;
michael@0 229 }
michael@0 230 bool debugMode() const {
michael@0 231 return flags_ & DEBUG_MODE;
michael@0 232 }
michael@0 233
michael@0 234 uint32_t prologueOffset() const {
michael@0 235 return prologueOffset_;
michael@0 236 }
michael@0 237 uint8_t *prologueEntryAddr() const {
michael@0 238 return method_->raw() + prologueOffset_;
michael@0 239 }
michael@0 240
michael@0 241 uint32_t epilogueOffset() const {
michael@0 242 return epilogueOffset_;
michael@0 243 }
michael@0 244 uint8_t *epilogueEntryAddr() const {
michael@0 245 return method_->raw() + epilogueOffset_;
michael@0 246 }
michael@0 247
michael@0 248 uint32_t postDebugPrologueOffset() const {
michael@0 249 return postDebugPrologueOffset_;
michael@0 250 }
michael@0 251 uint8_t *postDebugPrologueAddr() const {
michael@0 252 return method_->raw() + postDebugPrologueOffset_;
michael@0 253 }
michael@0 254
michael@0 255 ICEntry *icEntryList() {
michael@0 256 return (ICEntry *)(reinterpret_cast<uint8_t *>(this) + icEntriesOffset_);
michael@0 257 }
michael@0 258 PCMappingIndexEntry *pcMappingIndexEntryList() {
michael@0 259 return (PCMappingIndexEntry *)(reinterpret_cast<uint8_t *>(this) + pcMappingIndexOffset_);
michael@0 260 }
michael@0 261 uint8_t *pcMappingData() {
michael@0 262 return reinterpret_cast<uint8_t *>(this) + pcMappingOffset_;
michael@0 263 }
michael@0 264 FallbackICStubSpace *fallbackStubSpace() {
michael@0 265 return &fallbackStubSpace_;
michael@0 266 }
michael@0 267
michael@0 268 JitCode *method() const {
michael@0 269 return method_;
michael@0 270 }
michael@0 271 void setMethod(JitCode *code) {
michael@0 272 JS_ASSERT(!method_);
michael@0 273 method_ = code;
michael@0 274 }
michael@0 275
michael@0 276 JSObject *templateScope() const {
michael@0 277 return templateScope_;
michael@0 278 }
michael@0 279 void setTemplateScope(JSObject *templateScope) {
michael@0 280 JS_ASSERT(!templateScope_);
michael@0 281 templateScope_ = templateScope;
michael@0 282 }
michael@0 283
michael@0 284 void toggleBarriers(bool enabled) {
michael@0 285 method()->togglePreBarriers(enabled);
michael@0 286 }
michael@0 287
michael@0 288 bool containsCodeAddress(uint8_t *addr) const {
michael@0 289 return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
michael@0 290 }
michael@0 291
michael@0 292 ICEntry &icEntry(size_t index);
michael@0 293 ICEntry *maybeICEntryFromReturnOffset(CodeOffsetLabel returnOffset);
michael@0 294 ICEntry &icEntryFromReturnOffset(CodeOffsetLabel returnOffset);
michael@0 295 ICEntry &icEntryFromPCOffset(uint32_t pcOffset);
michael@0 296 ICEntry &icEntryForDebugModeRecompileFromPCOffset(uint32_t pcOffset);
michael@0 297 ICEntry &icEntryFromPCOffset(uint32_t pcOffset, ICEntry *prevLookedUpEntry);
michael@0 298 ICEntry *maybeICEntryFromReturnAddress(uint8_t *returnAddr);
michael@0 299 ICEntry &icEntryFromReturnAddress(uint8_t *returnAddr);
michael@0 300 uint8_t *returnAddressForIC(const ICEntry &ent);
michael@0 301
michael@0 302 size_t numICEntries() const {
michael@0 303 return icEntries_;
michael@0 304 }
michael@0 305
michael@0 306 void copyICEntries(JSScript *script, const ICEntry *entries, MacroAssembler &masm);
michael@0 307 void adoptFallbackStubs(FallbackICStubSpace *stubSpace);
michael@0 308
michael@0 309 PCMappingIndexEntry &pcMappingIndexEntry(size_t index);
michael@0 310 CompactBufferReader pcMappingReader(size_t indexEntry);
michael@0 311
michael@0 312 size_t numPCMappingIndexEntries() const {
michael@0 313 return pcMappingIndexEntries_;
michael@0 314 }
michael@0 315
michael@0 316 void copyPCMappingIndexEntries(const PCMappingIndexEntry *entries);
michael@0 317
michael@0 318 void copyPCMappingEntries(const CompactBufferWriter &entries);
michael@0 319 uint8_t *nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotInfo *slotInfo = nullptr);
michael@0 320 jsbytecode *pcForReturnOffset(JSScript *script, uint32_t nativeOffset);
michael@0 321 jsbytecode *pcForReturnAddress(JSScript *script, uint8_t *nativeAddress);
michael@0 322
michael@0 323 // Toggle debug traps (used for breakpoints and step mode) in the script.
michael@0 324 // If |pc| is nullptr, toggle traps for all ops in the script. Else, only
michael@0 325 // toggle traps at |pc|.
michael@0 326 void toggleDebugTraps(JSScript *script, jsbytecode *pc);
michael@0 327
michael@0 328 void toggleSPS(bool enable);
michael@0 329
michael@0 330 void noteAccessedGetter(uint32_t pcOffset);
michael@0 331 void noteArrayWriteHole(uint32_t pcOffset);
michael@0 332
michael@0 333 static size_t offsetOfFlags() {
michael@0 334 return offsetof(BaselineScript, flags_);
michael@0 335 }
michael@0 336
michael@0 337 static void writeBarrierPre(Zone *zone, BaselineScript *script);
michael@0 338
michael@0 339 uint32_t *bytecodeTypeMap() {
michael@0 340 JS_ASSERT(bytecodeTypeMapOffset_);
michael@0 341 return reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(this) + bytecodeTypeMapOffset_);
michael@0 342 }
michael@0 343 };
michael@0 344
michael@0 345 inline bool
michael@0 346 IsBaselineEnabled(JSContext *cx)
michael@0 347 {
michael@0 348 return cx->runtime()->options().baseline();
michael@0 349 }
michael@0 350
michael@0 351 MethodStatus
michael@0 352 CanEnterBaselineMethod(JSContext *cx, RunState &state);
michael@0 353
michael@0 354 MethodStatus
michael@0 355 CanEnterBaselineAtBranch(JSContext *cx, InterpreterFrame *fp, bool newType);
michael@0 356
michael@0 357 IonExecStatus
michael@0 358 EnterBaselineMethod(JSContext *cx, RunState &state);
michael@0 359
michael@0 360 IonExecStatus
michael@0 361 EnterBaselineAtBranch(JSContext *cx, InterpreterFrame *fp, jsbytecode *pc);
michael@0 362
michael@0 363 void
michael@0 364 FinishDiscardBaselineScript(FreeOp *fop, JSScript *script);
michael@0 365
michael@0 366 void
michael@0 367 AddSizeOfBaselineData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf, size_t *data,
michael@0 368 size_t *fallbackStubs);
michael@0 369
michael@0 370 void
michael@0 371 ToggleBaselineSPS(JSRuntime *runtime, bool enable);
michael@0 372
michael@0 373 struct BaselineBailoutInfo
michael@0 374 {
michael@0 375 // Pointer into the current C stack, where overwriting will start.
michael@0 376 uint8_t *incomingStack;
michael@0 377
michael@0 378 // The top and bottom heapspace addresses of the reconstructed stack
michael@0 379 // which will be copied to the bottom.
michael@0 380 uint8_t *copyStackTop;
michael@0 381 uint8_t *copyStackBottom;
michael@0 382
michael@0 383 // Fields to store the top-of-stack baseline values that are held
michael@0 384 // in registers. The setR0 and setR1 fields are flags indicating
michael@0 385 // whether each one is initialized.
michael@0 386 uint32_t setR0;
michael@0 387 Value valueR0;
michael@0 388 uint32_t setR1;
michael@0 389 Value valueR1;
michael@0 390
michael@0 391 // The value of the frame pointer register on resume.
michael@0 392 void *resumeFramePtr;
michael@0 393
michael@0 394 // The native code address to resume into.
michael@0 395 void *resumeAddr;
michael@0 396
michael@0 397 // If resuming into a TypeMonitor IC chain, this field holds the
michael@0 398 // address of the first stub in that chain. If this field is
michael@0 399 // set, then the actual jitcode resumed into is the jitcode for
michael@0 400 // the first stub, not the resumeAddr above. The resumeAddr
michael@0 401 // above, in this case, is pushed onto the stack so that the
michael@0 402 // TypeMonitor chain can tail-return into the main jitcode when done.
michael@0 403 ICStub *monitorStub;
michael@0 404
michael@0 405 // Number of baseline frames to push on the stack.
michael@0 406 uint32_t numFrames;
michael@0 407
michael@0 408 // The bailout kind.
michael@0 409 BailoutKind bailoutKind;
michael@0 410 };
michael@0 411
michael@0 412 uint32_t
michael@0 413 BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIterator &iter,
michael@0 414 bool invalidate, BaselineBailoutInfo **bailoutInfo,
michael@0 415 const ExceptionBailoutInfo *exceptionInfo = nullptr);
michael@0 416
michael@0 417 // Mark baseline scripts on the stack as active, so that they are not discarded
michael@0 418 // during GC.
michael@0 419 void
michael@0 420 MarkActiveBaselineScripts(Zone *zone);
michael@0 421
michael@0 422 MethodStatus
michael@0 423 BaselineCompile(JSContext *cx, JSScript *script);
michael@0 424
michael@0 425 } // namespace jit
michael@0 426 } // namespace js
michael@0 427
michael@0 428 #endif // JS_ION
michael@0 429
michael@0 430 #endif /* jit_BaselineJIT_h */

mercurial