summaryrefslogtreecommitdiffstats
path: root/js/src/jit/CacheIRReader.h
blob: affefdac010766cc889f0487e7336209828d435d (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
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * 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_CacheIRReader_h
#define jit_CacheIRReader_h

#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"

#include <stdint.h>
#include "NamespaceImports.h"

#include "jit/CacheIR.h"
#include "jit/CacheIRWriter.h"
#include "jit/CompactBuffer.h"
#include "js/ScalarType.h"
#include "js/Value.h"
#include "wasm/WasmValType.h"

enum class JSOp : uint8_t;

namespace js {

enum class UnaryMathFunction : uint8_t;

namespace gc {
enum class AllocKind : uint8_t;
}

namespace jit {

class CacheIRStubInfo;

// Helper class for reading CacheIR bytecode.
class MOZ_RAII CacheIRReader {
  CompactBufferReader buffer_;

  CacheIRReader(const CacheIRReader&) = delete;
  CacheIRReader& operator=(const CacheIRReader&) = delete;

 public:
  CacheIRReader(const uint8_t* start, const uint8_t* end)
      : buffer_(start, end) {}
  explicit CacheIRReader(const CacheIRWriter& writer)
      : CacheIRReader(writer.codeStart(), writer.codeEnd()) {}
  explicit CacheIRReader(const CacheIRStubInfo* stubInfo);

  bool more() const { return buffer_.more(); }

  CacheOp readOp() { return CacheOp(buffer_.readFixedUint16_t()); }
  CacheOp peekOp() { return CacheOp(buffer_.peekFixedUint16_t()); }

  // Skip data not currently used.
  void skip() { buffer_.readByte(); }
  void skip(uint32_t skipLength) {
    if (skipLength > 0) {
      buffer_.seek(buffer_.currentPosition(), skipLength);
    }
  }

  ValOperandId valOperandId() { return ValOperandId(buffer_.readByte()); }
  ValueTagOperandId valueTagOperandId() {
    return ValueTagOperandId(buffer_.readByte());
  }

  IntPtrOperandId intPtrOperandId() {
    return IntPtrOperandId(buffer_.readByte());
  }

  ObjOperandId objOperandId() { return ObjOperandId(buffer_.readByte()); }
  NumberOperandId numberOperandId() {
    return NumberOperandId(buffer_.readByte());
  }
  StringOperandId stringOperandId() {
    return StringOperandId(buffer_.readByte());
  }

  SymbolOperandId symbolOperandId() {
    return SymbolOperandId(buffer_.readByte());
  }

  BigIntOperandId bigIntOperandId() {
    return BigIntOperandId(buffer_.readByte());
  }

  BooleanOperandId booleanOperandId() {
    return BooleanOperandId(buffer_.readByte());
  }

  Int32OperandId int32OperandId() { return Int32OperandId(buffer_.readByte()); }

  uint32_t rawOperandId() { return buffer_.readByte(); }

  uint32_t stubOffset() { return buffer_.readByte() * sizeof(uintptr_t); }
  GuardClassKind guardClassKind() { return GuardClassKind(buffer_.readByte()); }
  ValueType valueType() { return ValueType(buffer_.readByte()); }
  wasm::ValType::Kind wasmValType() {
    return wasm::ValType::Kind(buffer_.readByte());
  }
  gc::AllocKind allocKind() { return gc::AllocKind(buffer_.readByte()); }
  CompletionKind completionKind() { return CompletionKind(buffer_.readByte()); }
  RealmFuses::FuseIndex realmFuseIndex() {
    return RealmFuses::FuseIndex(buffer_.readByte());
  }

  Scalar::Type scalarType() { return Scalar::Type(buffer_.readByte()); }
  JSWhyMagic whyMagic() { return JSWhyMagic(buffer_.readByte()); }
  JSOp jsop() { return JSOp(buffer_.readByte()); }
  int32_t int32Immediate() { return int32_t(buffer_.readFixedUint32_t()); }
  uint32_t uint32Immediate() { return buffer_.readFixedUint32_t(); }
  void* pointer() { return buffer_.readRawPointer(); }

  UnaryMathFunction unaryMathFunction() {
    return UnaryMathFunction(buffer_.readByte());
  }

  CallFlags callFlags() {
    // See CacheIRWriter::writeCallFlagsImm()
    uint8_t encoded = buffer_.readByte();
    CallFlags::ArgFormat format =
        CallFlags::ArgFormat(encoded & CallFlags::ArgFormatMask);
    bool isConstructing = encoded & CallFlags::IsConstructing;
    bool isSameRealm = encoded & CallFlags::IsSameRealm;
    bool needsUninitializedThis = encoded & CallFlags::NeedsUninitializedThis;
    MOZ_ASSERT_IF(needsUninitializedThis, isConstructing);
    switch (format) {
      case CallFlags::Unknown:
        MOZ_CRASH("Unexpected call flags");
      case CallFlags::Standard:
        return CallFlags(isConstructing, /*isSpread =*/false, isSameRealm,
                         needsUninitializedThis);
      case CallFlags::Spread:
        return CallFlags(isConstructing, /*isSpread =*/true, isSameRealm,
                         needsUninitializedThis);
      default:
        // The existing non-standard argument formats (FunCall and FunApply)
        // can't be constructors.
        MOZ_ASSERT(!isConstructing);
        return CallFlags(format);
    }
  }

  uint8_t readByte() { return buffer_.readByte(); }
  bool readBool() {
    uint8_t b = buffer_.readByte();
    MOZ_ASSERT(b <= 1);
    return bool(b);
  }

  const uint8_t* currentPosition() const { return buffer_.currentPosition(); }
};

}  // namespace jit
}  // namespace js

#endif /* jit_CacheIRReader_h */