blob: bd4edecb27c975e1ba3e05fee5c71f20e1f0dd1d [file] [log] [blame]
/* -*- 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 */
#ifndef jit_MIRGenerator_h
#define jit_MIRGenerator_h
// This file declares the data structures used to build a control-flow graph
// containing MIR.
#include "mozilla/Atomics.h"
#include <stdarg.h>
#include "jscntxt.h"
#include "jscompartment.h"
#include "jit/CompileInfo.h"
#include "jit/JitAllocPolicy.h"
#include "jit/JitCompartment.h"
#include "jit/MIR.h"
#ifdef JS_ION_PERF
# include "jit/PerfSpewer.h"
#include "jit/RegisterSets.h"
namespace js {
namespace jit {
class MIRGraph;
class OptimizationInfo;
class MIRGenerator
MIRGenerator(CompileCompartment* compartment, const JitCompileOptions& options,
TempAllocator* alloc, MIRGraph* graph,
const CompileInfo* info, const OptimizationInfo* optimizationInfo,
bool usesSignalHandlersForAsmJSOOB = false);
TempAllocator& alloc() {
return *alloc_;
MIRGraph& graph() {
return *graph_;
bool ensureBallast() {
return alloc().ensureBallast();
const JitRuntime* jitRuntime() const {
return GetJitContext()->runtime->jitRuntime();
const CompileInfo& info() const {
return *info_;
const OptimizationInfo& optimizationInfo() const {
return *optimizationInfo_;
template <typename T>
T* allocate(size_t count = 1) {
size_t bytes;
if (MOZ_UNLIKELY(!CalculateAllocSize<T>(count, &bytes)))
return nullptr;
return static_cast<T*>(alloc().allocate(bytes));
// Set an error state and prints a message. Returns false so errors can be
// propagated up.
bool abort(const char* message, ...);
bool abortFmt(const char* message, va_list ap);
bool errored() const {
return error_;
bool instrumentedProfiling() {
if (!instrumentedProfilingIsCached_) {
instrumentedProfiling_ = GetJitContext()->runtime->spsProfiler().enabled();
instrumentedProfilingIsCached_ = true;
return instrumentedProfiling_;
bool isProfilerInstrumentationEnabled() {
return !compilingAsmJS() && instrumentedProfiling();
bool isOptimizationTrackingEnabled() {
return isProfilerInstrumentationEnabled() && !info().isAnalysis();
bool safeForMinorGC() const {
return safeForMinorGC_;
void setNotSafeForMinorGC() {
safeForMinorGC_ = false;
// Whether the main thread is trying to cancel this build.
bool shouldCancel(const char* why) {
return cancelBuild_;
void cancel() {
cancelBuild_ = true;
void maybePause() {
if (pauseBuild_ && *pauseBuild_)
void setPauseFlag(mozilla::Atomic<bool, mozilla::Relaxed>* pauseBuild) {
pauseBuild_ = pauseBuild;
void disable() {
abortReason_ = AbortReason_Disable;
AbortReason abortReason() {
return abortReason_;
bool compilingAsmJS() const {
return info_->compilingAsmJS();
uint32_t maxAsmJSStackArgBytes() const {
return maxAsmJSStackArgBytes_;
uint32_t resetAsmJSMaxStackArgBytes() {
uint32_t old = maxAsmJSStackArgBytes_;
maxAsmJSStackArgBytes_ = 0;
return old;
void setAsmJSMaxStackArgBytes(uint32_t n) {
maxAsmJSStackArgBytes_ = n;
void setPerformsCall() {
performsCall_ = true;
bool performsCall() const {
return performsCall_;
// Traverses the graph to find if there's any SIMD instruction. Costful but
// the value is cached, so don't worry about calling it several times.
bool usesSimd();
bool modifiesFrameArguments() const {
return modifiesFrameArguments_;
typedef Vector<ObjectGroup*, 0, JitAllocPolicy> ObjectGroupVector;
// When abortReason() == AbortReason_PreliminaryObjects, all groups with
// preliminary objects which haven't been analyzed yet.
const ObjectGroupVector& abortedPreliminaryGroups() const {
return abortedPreliminaryGroups_;
CompileCompartment* compartment;
const CompileInfo* info_;
const OptimizationInfo* optimizationInfo_;
TempAllocator* alloc_;
JSFunction* fun_;
uint32_t nslots_;
MIRGraph* graph_;
AbortReason abortReason_;
bool shouldForceAbort_; // Force AbortReason_Disable
ObjectGroupVector abortedPreliminaryGroups_;
bool error_;
mozilla::Atomic<bool, mozilla::Relaxed>* pauseBuild_;
mozilla::Atomic<bool, mozilla::Relaxed> cancelBuild_;
uint32_t maxAsmJSStackArgBytes_;
bool performsCall_;
bool usesSimd_;
bool usesSimdCached_;
// Keep track of whether frame arguments are modified during execution.
// RegAlloc needs to know this as spilling values back to their register
// slots is not compatible with that.
bool modifiesFrameArguments_;
bool instrumentedProfiling_;
bool instrumentedProfilingIsCached_;
bool safeForMinorGC_;
void addAbortedPreliminaryGroup(ObjectGroup* group);
bool usesSignalHandlersForAsmJSOOB_;
void setForceAbort() {
shouldForceAbort_ = true;
bool shouldForceAbort() {
return shouldForceAbort_;
#if defined(JS_ION_PERF)
AsmJSPerfSpewer asmJSPerfSpewer_;
AsmJSPerfSpewer& perfSpewer() { return asmJSPerfSpewer_; }
const JitCompileOptions options;
bool needsAsmJSBoundsCheckBranch(const MAsmJSHeapAccess* access) const;
size_t foldableOffsetRange(const MAsmJSHeapAccess* access) const;
GraphSpewer gs_;
GraphSpewer& graphSpewer() {
return gs_;
} // namespace jit
} // namespace js
#endif /* jit_MIRGenerator_h */