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.

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

mercurial