author Gregor Wagner <gwagner@mozilla.com>
Mon, 04 Apr 2016 12:08:53 +0200
changeset 291532 e99061fde28a93d29e0032903d56cc6bec451557
parent 287476 cde0572b59f2f6bd294eabaf4969f4fd4400d2bc
permissions -rw-r--r--

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef jit_shared_BaselineCompiler_shared_h
#define jit_shared_BaselineCompiler_shared_h

#include "jit/BaselineFrameInfo.h"
#include "jit/BaselineIC.h"
#include "jit/BytecodeAnalysis.h"
#include "jit/MacroAssembler.h"

namespace js {
namespace jit {

class BaselineCompilerShared
    JSContext* cx;
    JSScript* script;
    jsbytecode* pc;
    MacroAssembler masm;
    bool ionCompileable_;
    bool ionOSRCompileable_;
    bool compileDebugInstrumentation_;

    TempAllocator& alloc_;
    BytecodeAnalysis analysis_;
    FrameInfo frame;

    FallbackICStubSpace stubSpace_;
    js::Vector<ICEntry, 16, SystemAllocPolicy> icEntries_;

    // Stores the native code offset for a bytecode pc.
    struct PCMappingEntry
        uint32_t pcOffset;
        uint32_t nativeOffset;
        PCMappingSlotInfo slotInfo;

        // If set, insert a PCMappingIndexEntry before encoding the
        // current entry.
        bool addIndexEntry;

    js::Vector<PCMappingEntry, 16, SystemAllocPolicy> pcMappingEntries_;

    // Labels for the 'movWithPatch' for loading IC entry pointers in
    // the generated IC-calling code in the main jitcode.  These need
    // to be patched with the actual icEntry offsets after the BaselineScript
    // has been allocated.
    struct ICLoadLabel {
        size_t icEntry;
        CodeOffset label;
    js::Vector<ICLoadLabel, 16, SystemAllocPolicy> icLoadLabels_;

    uint32_t pushedBeforeCall_;
#ifdef DEBUG
    bool inCall_;

    CodeOffset spsPushToggleOffset_;
    CodeOffset profilerEnterFrameToggleOffset_;
    CodeOffset profilerExitFrameToggleOffset_;
    CodeOffset traceLoggerEnterToggleOffset_;
    CodeOffset traceLoggerExitToggleOffset_;
    CodeOffset traceLoggerScriptTextIdOffset_;

    BaselineCompilerShared(JSContext* cx, TempAllocator& alloc, JSScript* script);

    ICEntry* allocateICEntry(ICStub* stub, ICEntry::Kind kind) {
        if (!stub)
            return nullptr;

        // Create the entry and add it to the vector.
        if (!icEntries_.append(ICEntry(script->pcToOffset(pc), kind))) {
            return nullptr;
        ICEntry& vecEntry = icEntries_.back();

        // Set the first stub for the IC entry to the fallback stub

        // Return pointer to the IC entry
        return &vecEntry;

    // Append an ICEntry without a stub.
    bool appendICEntry(ICEntry::Kind kind, uint32_t returnOffset) {
        ICEntry entry(script->pcToOffset(pc), kind);
        if (!icEntries_.append(entry)) {
            return false;
        return true;

    bool addICLoadLabel(CodeOffset label) {
        ICLoadLabel loadLabel;
        loadLabel.label = label;
        loadLabel.icEntry = icEntries_.length() - 1;
        if (!icLoadLabels_.append(loadLabel)) {
            return false;
        return true;

    JSFunction* function() const {
        // Not delazifying here is ok as the function is guaranteed to have
        // been delazified before compilation started.
        return script->functionNonDelazifying();

    ModuleObject* module() const {
        return script->module();

    PCMappingSlotInfo getStackTopSlotInfo() {
        MOZ_ASSERT(frame.numUnsyncedSlots() <= 2);
        switch (frame.numUnsyncedSlots()) {
          case 0:
            return PCMappingSlotInfo::MakeSlotInfo();
          case 1:
            return PCMappingSlotInfo::MakeSlotInfo(PCMappingSlotInfo::ToSlotLocation(frame.peek(-1)));
          case 2:
            return PCMappingSlotInfo::MakeSlotInfo(PCMappingSlotInfo::ToSlotLocation(frame.peek(-1)),

    template <typename T>
    void pushArg(const T& t) {
    void prepareVMCall();

    enum CallVMPhase {
    bool callVM(const VMFunction& fun, CallVMPhase phase=POST_INITIALIZE);

    bool callVMNonOp(const VMFunction& fun, CallVMPhase phase=POST_INITIALIZE) {
        if (!callVM(fun, phase))
            return false;
        return true;

    BytecodeAnalysis& analysis() {
        return analysis_;

    void setCompileDebugInstrumentation() {
        compileDebugInstrumentation_ = true;

} // namespace jit
} // namespace js

#endif /* jit_shared_BaselineCompiler_shared_h */