summaryrefslogtreecommitdiffstats
path: root/js/src/jit/shared/BaselineCompiler-shared.h
blob: 7d1402a9d0cf7ae2eb2d29d578cad915f212d945 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/* -*- 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
{
  protected:
    JSContext* cx;
    JSScript* script;
    jsbytecode* pc;
    MacroAssembler masm;
    bool ionCompileable_;
    bool ionOSRCompileable_;
    bool compileDebugInstrumentation_;

    TempAllocator& alloc_;
    BytecodeAnalysis analysis_;
    FrameInfo frame;

    FallbackICStubSpace stubSpace_;
    js::Vector<BaselineICEntry, 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_;
#endif

    CodeOffset spsPushToggleOffset_;
    CodeOffset profilerEnterFrameToggleOffset_;
    CodeOffset profilerExitFrameToggleOffset_;

    Vector<CodeOffset> traceLoggerToggleOffsets_;
    CodeOffset traceLoggerScriptTextIdOffset_;

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

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

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

        // Set the first stub for the IC entry to the fallback stub
        vecEntry.setFirstStub(stub);

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

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

    bool addICLoadLabel(CodeOffset label) {
        MOZ_ASSERT(!icEntries_.empty());
        ICLoadLabel loadLabel;
        loadLabel.label = label;
        loadLabel.icEntry = icEntries_.length() - 1;
        if (!icLoadLabels_.append(loadLabel)) {
            ReportOutOfMemory(cx);
            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:
          default:
            return PCMappingSlotInfo::MakeSlotInfo(PCMappingSlotInfo::ToSlotLocation(frame.peek(-1)),
                                                   PCMappingSlotInfo::ToSlotLocation(frame.peek(-2)));
        }
    }

    template <typename T>
    void pushArg(const T& t) {
        masm.Push(t);
    }
    void prepareVMCall();

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

    bool callVMNonOp(const VMFunction& fun, CallVMPhase phase=POST_INITIALIZE) {
        if (!callVM(fun, phase))
            return false;
        icEntries_.back().setFakeKind(ICEntry::Kind_NonOpCallVM);
        return true;
    }

  public:
    BytecodeAnalysis& analysis() {
        return analysis_;
    }

    void setCompileDebugInstrumentation() {
        compileDebugInstrumentation_ = true;
    }
};

} // namespace jit
} // namespace js

#endif /* jit_shared_BaselineCompiler_shared_h */