michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jit_shared_BaselineCompiler_shared_h michael@0: #define jit_shared_BaselineCompiler_shared_h michael@0: michael@0: #include "jit/BaselineFrameInfo.h" michael@0: #include "jit/BaselineIC.h" michael@0: #include "jit/BytecodeAnalysis.h" michael@0: #include "jit/IonMacroAssembler.h" michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: class BaselineCompilerShared michael@0: { michael@0: protected: michael@0: JSContext *cx; michael@0: JSScript *script; michael@0: jsbytecode *pc; michael@0: MacroAssembler masm; michael@0: bool ionCompileable_; michael@0: bool ionOSRCompileable_; michael@0: bool debugMode_; michael@0: michael@0: TempAllocator &alloc_; michael@0: BytecodeAnalysis analysis_; michael@0: FrameInfo frame; michael@0: michael@0: FallbackICStubSpace stubSpace_; michael@0: js::Vector icEntries_; michael@0: michael@0: // Stores the native code offset for a bytecode pc. michael@0: struct PCMappingEntry michael@0: { michael@0: uint32_t pcOffset; michael@0: uint32_t nativeOffset; michael@0: PCMappingSlotInfo slotInfo; michael@0: michael@0: // If set, insert a PCMappingIndexEntry before encoding the michael@0: // current entry. michael@0: bool addIndexEntry; michael@0: michael@0: void fixupNativeOffset(MacroAssembler &masm) { michael@0: CodeOffsetLabel offset(nativeOffset); michael@0: offset.fixup(&masm); michael@0: JS_ASSERT(offset.offset() <= UINT32_MAX); michael@0: nativeOffset = (uint32_t) offset.offset(); michael@0: } michael@0: }; michael@0: michael@0: js::Vector pcMappingEntries_; michael@0: michael@0: // Labels for the 'movWithPatch' for loading IC entry pointers in michael@0: // the generated IC-calling code in the main jitcode. These need michael@0: // to be patched with the actual icEntry offsets after the BaselineScript michael@0: // has been allocated. michael@0: struct ICLoadLabel { michael@0: size_t icEntry; michael@0: CodeOffsetLabel label; michael@0: }; michael@0: js::Vector icLoadLabels_; michael@0: michael@0: uint32_t pushedBeforeCall_; michael@0: mozilla::DebugOnly inCall_; michael@0: michael@0: CodeOffsetLabel spsPushToggleOffset_; michael@0: michael@0: BaselineCompilerShared(JSContext *cx, TempAllocator &alloc, JSScript *script); michael@0: michael@0: ICEntry *allocateICEntry(ICStub *stub, ICEntry::Kind kind) { michael@0: if (!stub) michael@0: return nullptr; michael@0: michael@0: // Create the entry and add it to the vector. michael@0: if (!icEntries_.append(ICEntry(script->pcToOffset(pc), kind))) michael@0: return nullptr; michael@0: ICEntry &vecEntry = icEntries_.back(); michael@0: michael@0: // Set the first stub for the IC entry to the fallback stub michael@0: vecEntry.setFirstStub(stub); michael@0: michael@0: // Return pointer to the IC entry michael@0: return &vecEntry; michael@0: } michael@0: michael@0: bool addICLoadLabel(CodeOffsetLabel label) { michael@0: JS_ASSERT(!icEntries_.empty()); michael@0: ICLoadLabel loadLabel; michael@0: loadLabel.label = label; michael@0: loadLabel.icEntry = icEntries_.length() - 1; michael@0: return icLoadLabels_.append(loadLabel); michael@0: } michael@0: michael@0: JSFunction *function() const { michael@0: // Not delazifying here is ok as the function is guaranteed to have michael@0: // been delazified before compilation started. michael@0: return script->functionNonDelazifying(); michael@0: } michael@0: michael@0: PCMappingSlotInfo getStackTopSlotInfo() { michael@0: JS_ASSERT(frame.numUnsyncedSlots() <= 2); michael@0: switch (frame.numUnsyncedSlots()) { michael@0: case 0: michael@0: return PCMappingSlotInfo::MakeSlotInfo(); michael@0: case 1: michael@0: return PCMappingSlotInfo::MakeSlotInfo(PCMappingSlotInfo::ToSlotLocation(frame.peek(-1))); michael@0: case 2: michael@0: default: michael@0: return PCMappingSlotInfo::MakeSlotInfo(PCMappingSlotInfo::ToSlotLocation(frame.peek(-1)), michael@0: PCMappingSlotInfo::ToSlotLocation(frame.peek(-2))); michael@0: } michael@0: } michael@0: michael@0: template michael@0: void pushArg(const T& t) { michael@0: masm.Push(t); michael@0: } michael@0: void prepareVMCall() { michael@0: pushedBeforeCall_ = masm.framePushed(); michael@0: inCall_ = true; michael@0: michael@0: // Ensure everything is synced. michael@0: frame.syncStack(0); michael@0: michael@0: // Save the frame pointer. michael@0: masm.Push(BaselineFrameReg); michael@0: } michael@0: michael@0: enum CallVMPhase { michael@0: POST_INITIALIZE, michael@0: PRE_INITIALIZE, michael@0: CHECK_OVER_RECURSED michael@0: }; michael@0: bool callVM(const VMFunction &fun, CallVMPhase phase=POST_INITIALIZE); michael@0: michael@0: public: michael@0: BytecodeAnalysis &analysis() { michael@0: return analysis_; michael@0: } michael@0: }; michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_shared_BaselineCompiler_shared_h */