LCOV - code coverage report
Current view: top level - js/src/jit - BaselineJIT.h (source / functions) Hit Total Coverage
Test: output.info Lines: 113 155 72.9 %
Date: 2017-07-14 16:53:18 Functions: 42 58 72.4 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #ifndef jit_BaselineJIT_h
       8             : #define jit_BaselineJIT_h
       9             : 
      10             : #include "mozilla/MemoryReporting.h"
      11             : 
      12             : #include "jscntxt.h"
      13             : #include "jscompartment.h"
      14             : 
      15             : #include "ds/LifoAlloc.h"
      16             : #include "jit/Bailouts.h"
      17             : #include "jit/IonCode.h"
      18             : #include "jit/MacroAssembler.h"
      19             : #include "vm/TraceLogging.h"
      20             : 
      21             : namespace js {
      22             : namespace jit {
      23             : 
      24             : class StackValue;
      25             : class BaselineICEntry;
      26             : class ICStub;
      27             : class ControlFlowGraph;
      28             : 
      29             : class PCMappingSlotInfo
      30             : {
      31             :     uint8_t slotInfo_;
      32             : 
      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 };
      39             : 
      40       61179 :     PCMappingSlotInfo()
      41       61179 :       : slotInfo_(0)
      42       61179 :     { }
      43             : 
      44       61179 :     explicit PCMappingSlotInfo(uint8_t slotInfo)
      45       61179 :       : slotInfo_(slotInfo)
      46       61179 :     { }
      47             : 
      48       51873 :     static inline bool ValidSlotLocation(SlotLocation loc) {
      49       51873 :         return (loc == SlotInR0) || (loc == SlotInR1) || (loc == SlotIgnore);
      50             :     }
      51             : 
      52             :     static SlotLocation ToSlotLocation(const StackValue* stackVal);
      53             : 
      54       22871 :     inline static PCMappingSlotInfo MakeSlotInfo() { return PCMappingSlotInfo(0); }
      55             : 
      56       24743 :     inline static PCMappingSlotInfo MakeSlotInfo(SlotLocation topSlotLoc) {
      57       24743 :         MOZ_ASSERT(ValidSlotLocation(topSlotLoc));
      58       24743 :         return PCMappingSlotInfo(1 | (topSlotLoc << 2));
      59             :     }
      60             : 
      61       13565 :     inline static PCMappingSlotInfo MakeSlotInfo(SlotLocation topSlotLoc, SlotLocation nextSlotLoc) {
      62       13565 :         MOZ_ASSERT(ValidSlotLocation(topSlotLoc));
      63       13565 :         MOZ_ASSERT(ValidSlotLocation(nextSlotLoc));
      64       13565 :         return PCMappingSlotInfo(2 | (topSlotLoc << 2) | (nextSlotLoc) << 4);
      65             :     }
      66             : 
      67           0 :     inline unsigned numUnsynced() const {
      68           0 :         return slotInfo_ & 0x3;
      69             :     }
      70           0 :     inline SlotLocation topSlotLocation() const {
      71           0 :         return static_cast<SlotLocation>((slotInfo_ >> 2) & 0x3);
      72             :     }
      73           0 :     inline SlotLocation nextSlotLocation() const {
      74           0 :         return static_cast<SlotLocation>((slotInfo_ >> 4) & 0x3);
      75             :     }
      76      122356 :     inline uint8_t toByte() const {
      77      122356 :         return slotInfo_;
      78             :     }
      79             : };
      80             : 
      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;
      90             : 
      91             :     // Native code offset.
      92             :     uint32_t nativeOffset;
      93             : 
      94             :     // Offset in the CompactBuffer where data for pcOffset starts.
      95             :     uint32_t bufferOffset;
      96             : };
      97             : 
      98             : // Describes a single wasm::ImportExit which jumps (via an import with
      99             : // the given index) directly to a BaselineScript or IonScript.
     100             : struct DependentWasmImport
     101             : {
     102             :     wasm::Instance* instance;
     103             :     size_t importIndex;
     104             : 
     105           0 :     DependentWasmImport(wasm::Instance& instance, size_t importIndex)
     106           0 :       : instance(&instance),
     107           0 :         importIndex(importIndex)
     108           0 :     { }
     109             : };
     110             : 
     111             : struct BaselineScript
     112             : {
     113             :   public:
     114             :     // Largest script that the baseline compiler will attempt to compile.
     115             : #if defined(JS_CODEGEN_ARM)
     116             :     // ARM branches can only reach 32MB, and the macroassembler doesn't mitigate
     117             :     // that limitation. Use a stricter limit on the acceptable script size to
     118             :     // avoid crashing when branches go out of range.
     119             :     static const uint32_t MAX_JSSCRIPT_LENGTH = 1000000u;
     120             : #else
     121             :     static const uint32_t MAX_JSSCRIPT_LENGTH = 0x0fffffffu;
     122             : #endif
     123             : 
     124             :     // Limit the locals on a given script so that stack check on baseline frames
     125             :     // doesn't overflow a uint32_t value.
     126             :     // (MAX_JSSCRIPT_SLOTS * sizeof(Value)) must fit within a uint32_t.
     127             :     static const uint32_t MAX_JSSCRIPT_SLOTS = 0xffffu;
     128             : 
     129             :   private:
     130             :     // Code pointer containing the actual method.
     131             :     HeapPtr<JitCode*> method_;
     132             : 
     133             :     // For functions with a call object, template objects to use for the call
     134             :     // object and decl env object (linked via the call object's enclosing
     135             :     // scope).
     136             :     HeapPtr<EnvironmentObject*> templateEnv_;
     137             : 
     138             :     // Allocated space for fallback stubs.
     139             :     FallbackICStubSpace fallbackStubSpace_;
     140             : 
     141             :     // If non-null, the list of wasm::Modules that contain an optimized call
     142             :     // directly to this script.
     143             :     Vector<DependentWasmImport>* dependentWasmImports_;
     144             : 
     145             :     // Native code offset right before the scope chain is initialized.
     146             :     uint32_t prologueOffset_;
     147             : 
     148             :     // Native code offset right before the frame is popped and the method
     149             :     // returned from.
     150             :     uint32_t epilogueOffset_;
     151             : 
     152             :     // The offsets for the toggledJump instructions for profiler instrumentation.
     153             :     uint32_t profilerEnterToggleOffset_;
     154             :     uint32_t profilerExitToggleOffset_;
     155             : 
     156             :     // The offsets and event used for Tracelogger toggling.
     157             : #ifdef JS_TRACE_LOGGING
     158             : # ifdef DEBUG
     159             :     bool traceLoggerScriptsEnabled_;
     160             :     bool traceLoggerEngineEnabled_;
     161             : # endif
     162             :     TraceLoggerEvent traceLoggerScriptEvent_;
     163             : #endif
     164             : 
     165             :     // Native code offsets right after the debug prologue VM call returns, or
     166             :     // would have returned. This offset is recorded even when debug mode is
     167             :     // off to aid on-stack debug mode recompilation.
     168             :     //
     169             :     // We don't need one for the debug epilogue because that always happens
     170             :     // right before the epilogue, so we just use the epilogue offset.
     171             :     uint32_t postDebugPrologueOffset_;
     172             : 
     173             :   public:
     174             :     enum Flag {
     175             :         // Flag set by JSScript::argumentsOptimizationFailed. Similar to
     176             :         // JSScript::needsArgsObj_, but can be read from JIT code.
     177             :         NEEDS_ARGS_OBJ = 1 << 0,
     178             : 
     179             :         // Flag set when discarding JIT code, to indicate this script is
     180             :         // on the stack and should not be discarded.
     181             :         ACTIVE = 1 << 1,
     182             : 
     183             :         // Flag set when the script contains any writes to its on-stack
     184             :         // (rather than call object stored) arguments.
     185             :         MODIFIES_ARGUMENTS = 1 << 2,
     186             : 
     187             :         // Flag set when compiled for use with Debugger. Handles various
     188             :         // Debugger hooks and compiles toggled calls for traps.
     189             :         HAS_DEBUG_INSTRUMENTATION = 1 << 3,
     190             : 
     191             :         // Flag set if this script has ever been Ion compiled, either directly
     192             :         // or inlined into another script. This is cleared when the script's
     193             :         // type information or caches are cleared.
     194             :         ION_COMPILED_OR_INLINED = 1 << 4,
     195             : 
     196             :         // Flag is set if this script has profiling instrumentation turned on.
     197             :         PROFILER_INSTRUMENTATION_ON = 1 << 5
     198             :     };
     199             : 
     200             :   private:
     201             :     uint32_t flags_;
     202             : 
     203             :   private:
     204             :     void trace(JSTracer* trc);
     205             : 
     206             :     uint32_t icEntriesOffset_;
     207             :     uint32_t icEntries_;
     208             : 
     209             :     uint32_t pcMappingIndexOffset_;
     210             :     uint32_t pcMappingIndexEntries_;
     211             : 
     212             :     uint32_t pcMappingOffset_;
     213             :     uint32_t pcMappingSize_;
     214             : 
     215             :     // List mapping indexes of bytecode type sets to the offset of the opcode
     216             :     // they correspond to, for use by TypeScript::BytecodeTypes.
     217             :     uint32_t bytecodeTypeMapOffset_;
     218             : 
     219             :     // For generator scripts, we store the native code address for each yield
     220             :     // instruction.
     221             :     uint32_t yieldEntriesOffset_;
     222             : 
     223             :     // By default tracelogger is disabled. Therefore we disable the logging code
     224             :     // by default. We store the offsets we must patch to enable the logging.
     225             :     uint32_t traceLoggerToggleOffsetsOffset_;
     226             :     uint32_t numTraceLoggerToggleOffsets_;
     227             : 
     228             :     // The total bytecode length of all scripts we inlined when we Ion-compiled
     229             :     // this script. 0 if Ion did not compile this script or if we didn't inline
     230             :     // anything.
     231             :     uint16_t inlinedBytecodeLength_;
     232             : 
     233             :     // The max inlining depth where we can still inline all functions we inlined
     234             :     // when we Ion-compiled this script. This starts as UINT8_MAX, since we have
     235             :     // no data yet, and won't affect inlining heuristics in that case. The value
     236             :     // is updated when we Ion-compile this script. See makeInliningDecision for
     237             :     // more info.
     238             :     uint8_t maxInliningDepth_;
     239             : 
     240             :     // An ion compilation that is ready, but isn't linked yet.
     241             :     IonBuilder *pendingBuilder_;
     242             : 
     243             :     ControlFlowGraph* controlFlowGraph_;
     244             : 
     245             :   public:
     246             :     // Do not call directly, use BaselineScript::New. This is public for cx->new_.
     247             :     BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
     248             :                    uint32_t profilerEnterToggleOffset,
     249             :                    uint32_t profilerExitToggleOffset,
     250             :                    uint32_t postDebugPrologueOffset);
     251             : 
     252        1092 :     ~BaselineScript() {
     253             :         // The contents of the fallback stub space are removed and freed
     254             :         // separately after the next minor GC. See BaselineScript::Destroy.
     255         546 :         MOZ_ASSERT(fallbackStubSpace_.isEmpty());
     256         546 :     }
     257             : 
     258             :     static BaselineScript* New(JSScript* jsscript,
     259             :                                uint32_t prologueOffset, uint32_t epilogueOffset,
     260             :                                uint32_t profilerEnterToggleOffset,
     261             :                                uint32_t profilerExitToggleOffset,
     262             :                                uint32_t postDebugPrologueOffset,
     263             :                                size_t icEntries,
     264             :                                size_t pcMappingIndexEntries, size_t pcMappingSize,
     265             :                                size_t bytecodeTypeMapEntries,
     266             :                                size_t yieldEntries,
     267             :                                size_t traceLoggerToggleOffsetEntries);
     268             : 
     269             :     static void Trace(JSTracer* trc, BaselineScript* script);
     270             :     static void Destroy(FreeOp* fop, BaselineScript* script);
     271             : 
     272             :     void purgeOptimizedStubs(Zone* zone);
     273             : 
     274             :     static inline size_t offsetOfMethod() {
     275             :         return offsetof(BaselineScript, method_);
     276             :     }
     277             : 
     278           0 :     void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, size_t* data,
     279             :                                 size_t* fallbackStubs) const {
     280           0 :         *data += mallocSizeOf(this);
     281             : 
     282             :         // |data| already includes the ICStubSpace itself, so use
     283             :         // sizeOfExcludingThis.
     284           0 :         *fallbackStubs += fallbackStubSpace_.sizeOfExcludingThis(mallocSizeOf);
     285           0 :     }
     286             : 
     287        1092 :     bool active() const {
     288        1092 :         return flags_ & ACTIVE;
     289             :     }
     290           0 :     void setActive() {
     291           0 :         flags_ |= ACTIVE;
     292           0 :     }
     293           0 :     void resetActive() {
     294           0 :         flags_ &= ~ACTIVE;
     295           0 :     }
     296             : 
     297           0 :     void setNeedsArgsObj() {
     298           0 :         flags_ |= NEEDS_ARGS_OBJ;
     299           0 :     }
     300             : 
     301          69 :     void setModifiesArguments() {
     302          69 :         flags_ |= MODIFIES_ARGUMENTS;
     303          69 :     }
     304           8 :     bool modifiesArguments() {
     305           8 :         return flags_ & MODIFIES_ARGUMENTS;
     306             :     }
     307             : 
     308           0 :     void setHasDebugInstrumentation() {
     309           0 :         flags_ |= HAS_DEBUG_INSTRUMENTATION;
     310           0 :     }
     311           0 :     bool hasDebugInstrumentation() const {
     312           0 :         return flags_ & HAS_DEBUG_INSTRUMENTATION;
     313             :     }
     314             : 
     315          43 :     void setIonCompiledOrInlined() {
     316          43 :         flags_ |= ION_COMPILED_OR_INLINED;
     317          43 :     }
     318           0 :     void clearIonCompiledOrInlined() {
     319           0 :         flags_ &= ~ION_COMPILED_OR_INLINED;
     320           0 :     }
     321          11 :     bool ionCompiledOrInlined() const {
     322          11 :         return flags_ & ION_COMPILED_OR_INLINED;
     323             :     }
     324             : 
     325             :     uint32_t prologueOffset() const {
     326             :         return prologueOffset_;
     327             :     }
     328           0 :     uint8_t* prologueEntryAddr() const {
     329           0 :         return method_->raw() + prologueOffset_;
     330             :     }
     331             : 
     332             :     uint32_t epilogueOffset() const {
     333             :         return epilogueOffset_;
     334             :     }
     335           0 :     uint8_t* epilogueEntryAddr() const {
     336           0 :         return method_->raw() + epilogueOffset_;
     337             :     }
     338             : 
     339             :     uint32_t postDebugPrologueOffset() const {
     340             :         return postDebugPrologueOffset_;
     341             :     }
     342           0 :     uint8_t* postDebugPrologueAddr() const {
     343           0 :         return method_->raw() + postDebugPrologueOffset_;
     344             :     }
     345             : 
     346     1038900 :     BaselineICEntry* icEntryList() {
     347     1038900 :         return (BaselineICEntry*)(reinterpret_cast<uint8_t*>(this) + icEntriesOffset_);
     348             :     }
     349         627 :     uint8_t** yieldEntryList() {
     350         627 :         return (uint8_t**)(reinterpret_cast<uint8_t*>(this) + yieldEntriesOffset_);
     351             :     }
     352        7874 :     PCMappingIndexEntry* pcMappingIndexEntryList() {
     353        7874 :         return (PCMappingIndexEntry*)(reinterpret_cast<uint8_t*>(this) + pcMappingIndexOffset_);
     354             :     }
     355        4897 :     uint8_t* pcMappingData() {
     356        4897 :         return reinterpret_cast<uint8_t*>(this) + pcMappingOffset_;
     357             :     }
     358        2138 :     FallbackICStubSpace* fallbackStubSpace() {
     359        2138 :         return &fallbackStubSpace_;
     360             :     }
     361             : 
     362        9379 :     JitCode* method() const {
     363        9379 :         return method_;
     364             :     }
     365         627 :     void setMethod(JitCode* code) {
     366         627 :         MOZ_ASSERT(!method_);
     367         627 :         method_ = code;
     368         627 :     }
     369             : 
     370           4 :     EnvironmentObject* templateEnvironment() const {
     371           4 :         return templateEnv_;
     372             :     }
     373         627 :     void setTemplateEnvironment(EnvironmentObject* templateEnv) {
     374         627 :         MOZ_ASSERT(!templateEnv_);
     375         627 :         templateEnv_ = templateEnv;
     376         627 :     }
     377             : 
     378           0 :     bool containsCodeAddress(uint8_t* addr) const {
     379           0 :         return method()->raw() <= addr && addr <= method()->raw() + method()->instructionsSize();
     380             :     }
     381             : 
     382             :     BaselineICEntry& icEntry(size_t index);
     383             :     BaselineICEntry& icEntryFromReturnOffset(CodeOffset returnOffset);
     384             :     BaselineICEntry& icEntryFromPCOffset(uint32_t pcOffset);
     385             :     BaselineICEntry& icEntryFromPCOffset(uint32_t pcOffset, BaselineICEntry* prevLookedUpEntry);
     386             :     BaselineICEntry& callVMEntryFromPCOffset(uint32_t pcOffset);
     387             :     BaselineICEntry& stackCheckICEntry(bool earlyCheck);
     388             :     BaselineICEntry& warmupCountICEntry();
     389             :     BaselineICEntry& icEntryFromReturnAddress(uint8_t* returnAddr);
     390             :     uint8_t* returnAddressForIC(const BaselineICEntry& ent);
     391             : 
     392     1324532 :     size_t numICEntries() const {
     393     1324532 :         return icEntries_;
     394             :     }
     395             : 
     396             :     void copyICEntries(JSScript* script, const BaselineICEntry* entries, MacroAssembler& masm);
     397             :     void adoptFallbackStubs(FallbackICStubSpace* stubSpace);
     398             : 
     399             :     void copyYieldAndAwaitEntries(JSScript* script, Vector<uint32_t>& yieldAndAwaitOffsets);
     400             : 
     401             :     PCMappingIndexEntry& pcMappingIndexEntry(size_t index);
     402             :     CompactBufferReader pcMappingReader(size_t indexEntry);
     403             : 
     404       16121 :     size_t numPCMappingIndexEntries() const {
     405       16121 :         return pcMappingIndexEntries_;
     406             :     }
     407             : 
     408             :     void copyPCMappingIndexEntries(const PCMappingIndexEntry* entries);
     409             :     void copyPCMappingEntries(const CompactBufferWriter& entries);
     410             : 
     411             :     uint8_t* nativeCodeForPC(JSScript* script, jsbytecode* pc,
     412             :                              PCMappingSlotInfo* slotInfo = nullptr);
     413             : 
     414             :     // Return the bytecode offset for a given native code address. Be careful
     415             :     // when using this method: we don't emit code for some bytecode ops, so
     416             :     // the result may not be accurate.
     417             :     jsbytecode* approximatePcForNativeAddress(JSScript* script, uint8_t* nativeAddress);
     418             : 
     419             :     MOZ_MUST_USE bool addDependentWasmImport(JSContext* cx, wasm::Instance& instance, uint32_t idx);
     420             :     void removeDependentWasmImport(wasm::Instance& instance, uint32_t idx);
     421             :     void unlinkDependentWasmImports(FreeOp* fop);
     422             :     void clearDependentWasmImports();
     423             : 
     424             :     // Toggle debug traps (used for breakpoints and step mode) in the script.
     425             :     // If |pc| is nullptr, toggle traps for all ops in the script. Else, only
     426             :     // toggle traps at |pc|.
     427             :     void toggleDebugTraps(JSScript* script, jsbytecode* pc);
     428             : 
     429             :     void toggleProfilerInstrumentation(bool enable);
     430           0 :     bool isProfilerInstrumentationOn() const {
     431           0 :         return flags_ & PROFILER_INSTRUMENTATION_ON;
     432             :     }
     433             : 
     434             : #ifdef JS_TRACE_LOGGING
     435             :     void initTraceLogger(JSRuntime* runtime, JSScript* script, const Vector<CodeOffset>& offsets);
     436             :     void toggleTraceLoggerScripts(JSRuntime* runtime, JSScript* script, bool enable);
     437             :     void toggleTraceLoggerEngine(bool enable);
     438             : 
     439         632 :     static size_t offsetOfTraceLoggerScriptEvent() {
     440         632 :         return offsetof(BaselineScript, traceLoggerScriptEvent_);
     441             :     }
     442             : 
     443        1258 :     uint32_t* traceLoggerToggleOffsets() {
     444        1258 :         MOZ_ASSERT(traceLoggerToggleOffsetsOffset_);
     445             :         return reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(this) +
     446        1258 :                                            traceLoggerToggleOffsetsOffset_);
     447             :     }
     448             : #endif
     449             : 
     450             :     void noteAccessedGetter(uint32_t pcOffset);
     451             :     void noteHasDenseAdd(uint32_t pcOffset);
     452             : 
     453          41 :     static size_t offsetOfFlags() {
     454          41 :         return offsetof(BaselineScript, flags_);
     455             :     }
     456           4 :     static size_t offsetOfYieldEntriesOffset() {
     457           4 :         return offsetof(BaselineScript, yieldEntriesOffset_);
     458             :     }
     459             : 
     460             :     static void writeBarrierPre(Zone* zone, BaselineScript* script);
     461             : 
     462       43135 :     uint32_t* bytecodeTypeMap() {
     463       43135 :         MOZ_ASSERT(bytecodeTypeMapOffset_);
     464       43135 :         return reinterpret_cast<uint32_t*>(reinterpret_cast<uint8_t*>(this) + bytecodeTypeMapOffset_);
     465             :     }
     466             : 
     467          33 :     uint8_t maxInliningDepth() const {
     468          33 :         return maxInliningDepth_;
     469             :     }
     470          11 :     void setMaxInliningDepth(uint32_t depth) {
     471          11 :         MOZ_ASSERT(depth <= UINT8_MAX);
     472          11 :         maxInliningDepth_ = depth;
     473          11 :     }
     474          11 :     void resetMaxInliningDepth() {
     475          11 :         maxInliningDepth_ = UINT8_MAX;
     476          11 :     }
     477             : 
     478          43 :     uint16_t inlinedBytecodeLength() const {
     479          43 :         return inlinedBytecodeLength_;
     480             :     }
     481           4 :     void setInlinedBytecodeLength(uint32_t len) {
     482           4 :         if (len > UINT16_MAX)
     483           0 :             len = UINT16_MAX;
     484           4 :         inlinedBytecodeLength_ = len;
     485           4 :     }
     486             : 
     487        1345 :     bool hasPendingIonBuilder() const {
     488        1345 :         return !!pendingBuilder_;
     489             :     }
     490             : 
     491          12 :     js::jit::IonBuilder* pendingIonBuilder() {
     492          12 :         MOZ_ASSERT(hasPendingIonBuilder());
     493          12 :         return pendingBuilder_;
     494             :     }
     495          16 :     void setPendingIonBuilder(JSRuntime* maybeRuntime, JSScript* script, js::jit::IonBuilder* builder) {
     496          16 :         MOZ_ASSERT(script->baselineScript() == this);
     497          16 :         MOZ_ASSERT(!builder || !hasPendingIonBuilder());
     498             : 
     499          16 :         if (script->isIonCompilingOffThread())
     500           8 :             script->setIonScript(maybeRuntime, ION_PENDING_SCRIPT);
     501             : 
     502          16 :         pendingBuilder_ = builder;
     503             : 
     504             :         // lazy linking cannot happen during asmjs to ion.
     505          16 :         clearDependentWasmImports();
     506             : 
     507          16 :         script->updateBaselineOrIonRaw(maybeRuntime);
     508          16 :     }
     509           8 :     void removePendingIonBuilder(JSScript* script) {
     510           8 :         setPendingIonBuilder(nullptr, script, nullptr);
     511           8 :         if (script->maybeIonScript() == ION_PENDING_SCRIPT)
     512           8 :             script->setIonScript(nullptr, nullptr);
     513           8 :     }
     514             : 
     515         132 :     const ControlFlowGraph* controlFlowGraph() const {
     516         132 :         return controlFlowGraph_;
     517             :     }
     518             : 
     519          15 :     void setControlFlowGraph(ControlFlowGraph* controlFlowGraph) {
     520          15 :         controlFlowGraph_ = controlFlowGraph;
     521          15 :     }
     522             : 
     523             : };
     524             : static_assert(sizeof(BaselineScript) % sizeof(uintptr_t) == 0,
     525             :               "The data attached to the script must be aligned for fast JIT access.");
     526             : 
     527             : inline bool
     528       71383 : IsBaselineEnabled(JSContext* cx)
     529             : {
     530             : #ifdef JS_CODEGEN_NONE
     531             :     return false;
     532             : #else
     533       71383 :     return cx->options().baseline();
     534             : #endif
     535             : }
     536             : 
     537             : MethodStatus
     538             : CanEnterBaselineMethod(JSContext* cx, RunState& state);
     539             : 
     540             : MethodStatus
     541             : CanEnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, bool newType);
     542             : 
     543             : JitExecStatus
     544             : EnterBaselineMethod(JSContext* cx, RunState& state);
     545             : 
     546             : JitExecStatus
     547             : EnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc);
     548             : 
     549             : void
     550             : FinishDiscardBaselineScript(FreeOp* fop, JSScript* script);
     551             : 
     552             : void
     553             : AddSizeOfBaselineData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf, size_t* data,
     554             :                       size_t* fallbackStubs);
     555             : 
     556             : void
     557             : ToggleBaselineProfiling(JSRuntime* runtime, bool enable);
     558             : 
     559             : void
     560             : ToggleBaselineTraceLoggerScripts(JSRuntime* runtime, bool enable);
     561             : void
     562             : ToggleBaselineTraceLoggerEngine(JSRuntime* runtime, bool enable);
     563             : 
     564             : struct BaselineBailoutInfo
     565             : {
     566             :     // Pointer into the current C stack, where overwriting will start.
     567             :     uint8_t* incomingStack;
     568             : 
     569             :     // The top and bottom heapspace addresses of the reconstructed stack
     570             :     // which will be copied to the bottom.
     571             :     uint8_t* copyStackTop;
     572             :     uint8_t* copyStackBottom;
     573             : 
     574             :     // Fields to store the top-of-stack baseline values that are held
     575             :     // in registers.  The setR0 and setR1 fields are flags indicating
     576             :     // whether each one is initialized.
     577             :     uint32_t setR0;
     578             :     Value valueR0;
     579             :     uint32_t setR1;
     580             :     Value valueR1;
     581             : 
     582             :     // The value of the frame pointer register on resume.
     583             :     void* resumeFramePtr;
     584             : 
     585             :     // The native code address to resume into.
     586             :     void* resumeAddr;
     587             : 
     588             :     // The bytecode pc where we will resume.
     589             :     jsbytecode* resumePC;
     590             : 
     591             :     // The bytecode pc of try block and fault block.
     592             :     jsbytecode* tryPC;
     593             :     jsbytecode* faultPC;
     594             : 
     595             :     // If resuming into a TypeMonitor IC chain, this field holds the
     596             :     // address of the first stub in that chain.  If this field is
     597             :     // set, then the actual jitcode resumed into is the jitcode for
     598             :     // the first stub, not the resumeAddr above.  The resumeAddr
     599             :     // above, in this case, is pushed onto the stack so that the
     600             :     // TypeMonitor chain can tail-return into the main jitcode when done.
     601             :     ICStub* monitorStub;
     602             : 
     603             :     // Number of baseline frames to push on the stack.
     604             :     uint32_t numFrames;
     605             : 
     606             :     // If Ion bailed out on a global script before it could perform the global
     607             :     // declaration conflicts check. In such cases the baseline script is
     608             :     // resumed at the first pc instead of the prologue, so an extra flag is
     609             :     // needed to perform the check.
     610             :     bool checkGlobalDeclarationConflicts;
     611             : 
     612             :     // The bailout kind.
     613             :     BailoutKind bailoutKind;
     614             : };
     615             : 
     616             : uint32_t
     617             : BailoutIonToBaseline(JSContext* cx, JitActivation* activation, JitFrameIterator& iter,
     618             :                      bool invalidate, BaselineBailoutInfo** bailoutInfo,
     619             :                      const ExceptionBailoutInfo* exceptionInfo);
     620             : 
     621             : // Mark baseline scripts on the stack as active, so that they are not discarded
     622             : // during GC.
     623             : void
     624             : MarkActiveBaselineScripts(Zone* zone);
     625             : 
     626             : MethodStatus
     627             : BaselineCompile(JSContext* cx, JSScript* script, bool forceDebugInstrumentation = false);
     628             : 
     629             : } // namespace jit
     630             : } // namespace js
     631             : 
     632             : namespace JS {
     633             : 
     634             : template <>
     635             : struct DeletePolicy<js::jit::BaselineScript>
     636             : {
     637         627 :     explicit DeletePolicy(JSRuntime* rt) : rt_(rt) {}
     638             :     void operator()(const js::jit::BaselineScript* script);
     639             : 
     640             :   private:
     641             :     JSRuntime* rt_;
     642             : };
     643             : 
     644             : } // namespace JS
     645             : 
     646             : #endif /* jit_BaselineJIT_h */

Generated by: LCOV version 1.13