1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_REGEXP_OPCODE_H 17 #define ECMASCRIPT_REGEXP_OPCODE_H 18 19 #include <list> 20 21 #include "ecmascript/mem/dyn_chunk.h" 22 23 namespace panda { 24 namespace ecmascript { 25 class RegExpOpCode { 26 public: 27 enum : uint8_t { 28 OP_SAVE_START = 0U, 29 OP_SAVE_END, 30 OP_CHAR, 31 OP_GOTO, 32 OP_SPLIT_FIRST, 33 OP_SPLIT_NEXT, 34 OP_NEGATIVE_MATCH_AHEAD, 35 OP_MATCH_AHEAD, 36 OP_MATCH, 37 OP_LOOP, 38 OP_LOOP_GREEDY, 39 OP_PUSH_CHAR, 40 OP_CHECK_CHAR, 41 OP_PUSH, 42 OP_POP, 43 OP_SAVE_RESET, 44 OP_LINE_START, 45 OP_LINE_END, 46 OP_WORD_BOUNDARY, 47 OP_NOT_WORD_BOUNDARY, 48 OP_ALL, 49 OP_DOTS, 50 OP_MATCH_END, 51 OP_PREV, 52 OP_RANGE, 53 OP_BACKREFERENCE, 54 OP_BACKWARD_BACKREFERENCE, 55 OP_CHAR32, 56 OP_RANGE32, 57 OP_SPARSE, 58 OP_INVALID, 59 }; 60 61 static constexpr size_t OP_SIZE_ONE = 1; 62 static constexpr size_t OP_SIZE_TWO = 2; 63 static constexpr size_t OP_SIZE_THREE = 3; 64 static constexpr size_t OP_SIZE_FOUR = 4; 65 static constexpr size_t OP_SIZE_FIVE = 5; 66 static constexpr size_t OP_SIZE_SIX = 6; 67 static constexpr size_t OP_SIZE_EIGHT = 8; 68 static constexpr size_t OP_SIZE_NINE = 9; 69 static constexpr size_t OP_SIZE_THIRTEEN = 13; 70 static constexpr uint32_t INVALID_PARA = 0xffffffff; 71 72 RegExpOpCode(uint8_t opCode, int size); 73 NO_COPY_SEMANTIC(RegExpOpCode); 74 NO_MOVE_SEMANTIC(RegExpOpCode); 75 76 virtual ~RegExpOpCode() = default; 77 static RegExpOpCode *GetRegExpOpCode(const DynChunk &buf, int pcOffset); 78 static RegExpOpCode *GetRegExpOpCode(uint8_t opCode); 79 static void DumpRegExpOpCode(std::ostream &out, const DynChunk &buf, uint32_t size); GetSize()80 inline uint8_t GetSize() const 81 { 82 return size_; 83 } GetOpCode()84 inline uint8_t GetOpCode() const 85 { 86 return opCode_; 87 } GetDynChunkfSize(const DynChunk & buf)88 inline int GetDynChunkfSize(const DynChunk &buf) const 89 { 90 return buf.size_; 91 } 92 virtual uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const = 0; 93 94 private: 95 uint8_t opCode_ {0}; 96 uint8_t size_ {0}; 97 }; 98 99 class SaveStartOpCode : public RegExpOpCode { 100 public: SaveStartOpCode()101 SaveStartOpCode() : RegExpOpCode(OP_SAVE_START, RegExpOpCode::OP_SIZE_TWO) {} 102 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 103 ~SaveStartOpCode() override = default; 104 NO_COPY_SEMANTIC(SaveStartOpCode); 105 NO_MOVE_SEMANTIC(SaveStartOpCode); 106 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 107 }; 108 109 class SaveEndOpCode : public RegExpOpCode { 110 public: SaveEndOpCode()111 SaveEndOpCode() : RegExpOpCode(OP_SAVE_END, RegExpOpCode::OP_SIZE_TWO) {} 112 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 113 ~SaveEndOpCode() override = default; 114 NO_COPY_SEMANTIC(SaveEndOpCode); 115 NO_MOVE_SEMANTIC(SaveEndOpCode); 116 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 117 }; 118 119 class CharOpCode : public RegExpOpCode { 120 public: CharOpCode()121 CharOpCode() : RegExpOpCode(OP_CHAR, RegExpOpCode::OP_SIZE_THREE) {} 122 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 123 ~CharOpCode() override = default; 124 NO_COPY_SEMANTIC(CharOpCode); 125 NO_MOVE_SEMANTIC(CharOpCode); 126 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 127 }; 128 129 class GotoOpCode : public RegExpOpCode { 130 public: GotoOpCode()131 GotoOpCode() : RegExpOpCode(OP_GOTO, RegExpOpCode::OP_SIZE_FIVE) {} 132 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 133 void UpdateOpPara(DynChunk *buf, uint32_t offset, uint32_t para) const; 134 ~GotoOpCode() override = default; 135 NO_COPY_SEMANTIC(GotoOpCode); 136 NO_MOVE_SEMANTIC(GotoOpCode); 137 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 138 }; 139 140 class SplitNextOpCode : public RegExpOpCode { 141 public: SplitNextOpCode()142 SplitNextOpCode() : RegExpOpCode(OP_SPLIT_NEXT, RegExpOpCode::OP_SIZE_FIVE) {} 143 uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const; 144 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 145 ~SplitNextOpCode() override = default; 146 NO_COPY_SEMANTIC(SplitNextOpCode); 147 NO_MOVE_SEMANTIC(SplitNextOpCode); 148 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 149 }; 150 151 class SplitFirstOpCode : public RegExpOpCode { 152 public: SplitFirstOpCode()153 SplitFirstOpCode() : RegExpOpCode(OP_SPLIT_FIRST, RegExpOpCode::OP_SIZE_FIVE) {} 154 uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const; 155 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 156 ~SplitFirstOpCode() override = default; 157 NO_COPY_SEMANTIC(SplitFirstOpCode); 158 NO_MOVE_SEMANTIC(SplitFirstOpCode); 159 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 160 }; 161 162 class PushOpCode : public RegExpOpCode { 163 public: PushOpCode()164 PushOpCode() : RegExpOpCode(OP_PUSH, RegExpOpCode::OP_SIZE_ONE) {} 165 uint32_t InsertOpCode(DynChunk *buf, uint32_t offset) const; 166 ~PushOpCode() override = default; 167 NO_COPY_SEMANTIC(PushOpCode); 168 NO_MOVE_SEMANTIC(PushOpCode); 169 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 170 }; 171 172 class PopOpCode : public RegExpOpCode { 173 public: PopOpCode()174 PopOpCode() : RegExpOpCode(OP_POP, RegExpOpCode::OP_SIZE_ONE) {} 175 uint32_t EmitOpCode(DynChunk *buf) const; 176 ~PopOpCode() override = default; 177 NO_COPY_SEMANTIC(PopOpCode); 178 NO_MOVE_SEMANTIC(PopOpCode); 179 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 180 }; 181 182 class PushCharOpCode : public RegExpOpCode { 183 public: PushCharOpCode()184 PushCharOpCode() : RegExpOpCode(OP_PUSH_CHAR, RegExpOpCode::OP_SIZE_ONE) {} 185 uint32_t InsertOpCode(DynChunk *buf, uint32_t offset) const; 186 ~PushCharOpCode() override = default; 187 NO_COPY_SEMANTIC(PushCharOpCode); 188 NO_MOVE_SEMANTIC(PushCharOpCode); 189 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 190 }; 191 192 class CheckCharOpCode : public RegExpOpCode { 193 public: CheckCharOpCode()194 CheckCharOpCode() : RegExpOpCode(OP_CHECK_CHAR, RegExpOpCode::OP_SIZE_FIVE) {} 195 uint32_t EmitOpCode(DynChunk *buf, uint32_t offset) const; 196 ~CheckCharOpCode() override = default; 197 NO_COPY_SEMANTIC(CheckCharOpCode); 198 NO_MOVE_SEMANTIC(CheckCharOpCode); 199 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 200 }; 201 202 class LoopOpCode : public RegExpOpCode { 203 public: LoopOpCode()204 LoopOpCode() : RegExpOpCode(OP_LOOP, RegExpOpCode::OP_SIZE_THIRTEEN) {} 205 uint32_t EmitOpCode(DynChunk *buf, uint32_t start, uint32_t min, uint32_t max) const; 206 ~LoopOpCode() override = default; 207 NO_COPY_SEMANTIC(LoopOpCode); 208 NO_MOVE_SEMANTIC(LoopOpCode); 209 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 210 }; 211 212 class LoopGreedyOpCode : public RegExpOpCode { 213 public: LoopGreedyOpCode()214 LoopGreedyOpCode() : RegExpOpCode(OP_LOOP_GREEDY, RegExpOpCode::OP_SIZE_THIRTEEN) {} 215 uint32_t EmitOpCode(DynChunk *buf, uint32_t start, uint32_t min, uint32_t max) const; 216 ~LoopGreedyOpCode() override = default; 217 NO_COPY_SEMANTIC(LoopGreedyOpCode); 218 NO_MOVE_SEMANTIC(LoopGreedyOpCode); 219 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 220 }; 221 222 class SaveResetOpCode : public RegExpOpCode { 223 public: SaveResetOpCode()224 SaveResetOpCode() : RegExpOpCode(OP_SAVE_RESET, RegExpOpCode::OP_SIZE_THREE) {} 225 uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t start, uint32_t end) const; 226 ~SaveResetOpCode() override = default; 227 NO_COPY_SEMANTIC(SaveResetOpCode); 228 NO_MOVE_SEMANTIC(SaveResetOpCode); 229 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 230 }; 231 232 class MatchOpCode : public RegExpOpCode { 233 public: MatchOpCode()234 MatchOpCode() : RegExpOpCode(OP_MATCH, RegExpOpCode::OP_SIZE_ONE) {} 235 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 236 ~MatchOpCode() override = default; 237 NO_COPY_SEMANTIC(MatchOpCode); 238 NO_MOVE_SEMANTIC(MatchOpCode); 239 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 240 }; 241 242 class MatchEndOpCode : public RegExpOpCode { 243 public: MatchEndOpCode()244 MatchEndOpCode() : RegExpOpCode(OP_MATCH_END, RegExpOpCode::OP_SIZE_ONE) {} 245 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 246 ~MatchEndOpCode() override = default; 247 NO_COPY_SEMANTIC(MatchEndOpCode); 248 NO_MOVE_SEMANTIC(MatchEndOpCode); 249 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 250 }; 251 252 class LineStartOpCode : public RegExpOpCode { 253 public: LineStartOpCode()254 LineStartOpCode() : RegExpOpCode(OP_LINE_START, RegExpOpCode::OP_SIZE_ONE) {} 255 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 256 ~LineStartOpCode() override = default; 257 NO_COPY_SEMANTIC(LineStartOpCode); 258 NO_MOVE_SEMANTIC(LineStartOpCode); 259 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 260 }; 261 262 class LineEndOpCode : public RegExpOpCode { 263 public: LineEndOpCode()264 LineEndOpCode() : RegExpOpCode(OP_LINE_END, RegExpOpCode::OP_SIZE_ONE) {} 265 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 266 ~LineEndOpCode() override = default; 267 NO_COPY_SEMANTIC(LineEndOpCode); 268 NO_MOVE_SEMANTIC(LineEndOpCode); 269 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 270 }; 271 272 class WordBoundaryOpCode : public RegExpOpCode { 273 public: WordBoundaryOpCode()274 WordBoundaryOpCode() : RegExpOpCode(OP_WORD_BOUNDARY, RegExpOpCode::OP_SIZE_ONE) {} 275 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 276 ~WordBoundaryOpCode() override = default; 277 NO_COPY_SEMANTIC(WordBoundaryOpCode); 278 NO_MOVE_SEMANTIC(WordBoundaryOpCode); 279 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 280 }; 281 282 class NotWordBoundaryOpCode : public RegExpOpCode { 283 public: NotWordBoundaryOpCode()284 NotWordBoundaryOpCode() : RegExpOpCode(OP_NOT_WORD_BOUNDARY, RegExpOpCode::OP_SIZE_ONE) {} 285 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 286 ~NotWordBoundaryOpCode() override = default; 287 NO_COPY_SEMANTIC(NotWordBoundaryOpCode); 288 NO_MOVE_SEMANTIC(NotWordBoundaryOpCode); 289 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 290 }; 291 292 class AllOpCode : public RegExpOpCode { 293 public: AllOpCode()294 AllOpCode() : RegExpOpCode(OP_ALL, RegExpOpCode::OP_SIZE_ONE) {} 295 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 296 ~AllOpCode() override = default; 297 NO_COPY_SEMANTIC(AllOpCode); 298 NO_MOVE_SEMANTIC(AllOpCode); 299 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 300 }; 301 302 class DotsOpCode : public RegExpOpCode { 303 public: DotsOpCode()304 DotsOpCode() : RegExpOpCode(OP_DOTS, RegExpOpCode::OP_SIZE_ONE) {} 305 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 306 ~DotsOpCode() override = default; 307 NO_COPY_SEMANTIC(DotsOpCode); 308 NO_MOVE_SEMANTIC(DotsOpCode); 309 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 310 }; 311 312 class RangeSet { 313 public: 314 RangeSet() = default; RangeSet(uint32_t value)315 explicit RangeSet(uint32_t value) 316 { 317 Insert(value, value); 318 } RangeSet(uint32_t start,uint32_t end)319 RangeSet(uint32_t start, uint32_t end) 320 { 321 Insert(start, end); 322 } RangeSet(const std::list<std::pair<uint32_t,uint32_t>> & rangeSet)323 explicit RangeSet(const std::list<std::pair<uint32_t, uint32_t>> &rangeSet) 324 { 325 rangeSet_ = rangeSet; 326 } 327 ~RangeSet() = default; 328 IsIntersect(uint64_t start,uint64_t end,uint64_t start1,uint64_t end1)329 inline bool IsIntersect(uint64_t start, uint64_t end, uint64_t start1, uint64_t end1) const 330 { 331 return ((start1 > start) && (start1 < end)) || ((start > start1) && (start < end1)); 332 } IsAdjacent(uint64_t start,uint64_t end,uint64_t start1,uint64_t end1)333 inline bool IsAdjacent(uint64_t start, uint64_t end, uint64_t start1, uint64_t end1) const 334 { 335 return ((end == start1 || (end + 1) == start1)) || ((end1 == start) || (end1 + 1 == start)); 336 } 337 338 inline bool operator==(const RangeSet &other) const 339 { 340 return rangeSet_ == other.rangeSet_; 341 } 342 IsContain(uint32_t value)343 inline bool IsContain(uint32_t value) const 344 { 345 for (auto range : rangeSet_) { 346 if (value >= range.first && value <= range.second) { 347 return true; 348 } 349 } 350 return false; 351 } HighestValue()352 inline uint32_t HighestValue() const 353 { 354 if (!rangeSet_.empty()) { 355 return rangeSet_.back().second; 356 } 357 return 0; 358 } 359 RangeSet(RangeSet const &) = default; 360 RangeSet &operator=(RangeSet const &) = default; 361 RangeSet(RangeSet &&) = default; 362 RangeSet &operator=(RangeSet &&) = default; 363 364 void Insert(uint32_t start, uint32_t end); 365 void Insert(const RangeSet &s1); 366 void Invert(bool isUtf16); 367 void Inter(RangeSet &cr, const RangeSet &s1); 368 void Compress(); 369 370 private: 371 friend class RangeOpCode; 372 friend class Range32OpCode; 373 std::list<std::pair<uint32_t, uint32_t>> rangeSet_ {}; 374 }; 375 376 class RangeOpCode : public RegExpOpCode { 377 public: RangeOpCode()378 RangeOpCode() : RegExpOpCode(OP_RANGE, RegExpOpCode::OP_SIZE_ONE) {} 379 ~RangeOpCode() override = default; 380 NO_COPY_SEMANTIC(RangeOpCode); 381 NO_MOVE_SEMANTIC(RangeOpCode); 382 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 383 uint32_t InsertOpCode(DynChunk *buf, const RangeSet &rangeSet) const; 384 }; 385 386 class MatchAheadOpCode : public RegExpOpCode { 387 public: MatchAheadOpCode()388 MatchAheadOpCode() : RegExpOpCode(OP_MATCH_AHEAD, RegExpOpCode::OP_SIZE_FIVE) {} 389 ~MatchAheadOpCode() override = default; 390 NO_COPY_SEMANTIC(MatchAheadOpCode); 391 NO_MOVE_SEMANTIC(MatchAheadOpCode); 392 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 393 uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const; 394 }; 395 396 class NegativeMatchAheadOpCode : public RegExpOpCode { 397 public: NegativeMatchAheadOpCode()398 NegativeMatchAheadOpCode() : RegExpOpCode(OP_NEGATIVE_MATCH_AHEAD, RegExpOpCode::OP_SIZE_FIVE) {} 399 uint32_t InsertOpCode(DynChunk *buf, uint32_t offset, uint32_t para) const; 400 ~NegativeMatchAheadOpCode() override = default; 401 NO_COPY_SEMANTIC(NegativeMatchAheadOpCode); 402 NO_MOVE_SEMANTIC(NegativeMatchAheadOpCode); 403 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 404 }; 405 406 class PrevOpCode : public RegExpOpCode { 407 public: PrevOpCode()408 PrevOpCode() : RegExpOpCode(OP_PREV, RegExpOpCode::OP_SIZE_ONE) {} 409 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 410 ~PrevOpCode() override = default; 411 NO_COPY_SEMANTIC(PrevOpCode); 412 NO_MOVE_SEMANTIC(PrevOpCode); 413 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 414 }; 415 416 class BackReferenceOpCode : public RegExpOpCode { 417 public: BackReferenceOpCode()418 BackReferenceOpCode() : RegExpOpCode(OP_BACKREFERENCE, RegExpOpCode::OP_SIZE_TWO) {} 419 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 420 ~BackReferenceOpCode() override = default; 421 NO_COPY_SEMANTIC(BackReferenceOpCode); 422 NO_MOVE_SEMANTIC(BackReferenceOpCode); 423 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 424 }; 425 426 class BackwardBackReferenceOpCode : public RegExpOpCode { 427 public: BackwardBackReferenceOpCode()428 BackwardBackReferenceOpCode() : RegExpOpCode(OP_BACKWARD_BACKREFERENCE, RegExpOpCode::OP_SIZE_TWO) {} 429 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 430 ~BackwardBackReferenceOpCode() override = default; 431 NO_COPY_SEMANTIC(BackwardBackReferenceOpCode); 432 NO_MOVE_SEMANTIC(BackwardBackReferenceOpCode); 433 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 434 }; 435 436 class Char32OpCode : public RegExpOpCode { 437 public: Char32OpCode()438 Char32OpCode() : RegExpOpCode(OP_CHAR32, RegExpOpCode::OP_SIZE_FIVE) {} 439 uint32_t EmitOpCode(DynChunk *buf, uint32_t para) const; 440 ~Char32OpCode() override = default; 441 NO_COPY_SEMANTIC(Char32OpCode); 442 NO_MOVE_SEMANTIC(Char32OpCode); 443 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 444 }; 445 446 class Range32OpCode : public RegExpOpCode { 447 public: Range32OpCode()448 Range32OpCode() : RegExpOpCode(OP_RANGE32, RegExpOpCode::OP_SIZE_ONE) {} 449 ~Range32OpCode() override = default; 450 NO_COPY_SEMANTIC(Range32OpCode); 451 NO_MOVE_SEMANTIC(Range32OpCode); 452 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 453 uint32_t InsertOpCode(DynChunk *buf, const RangeSet &rangeSet) const; 454 }; 455 456 class SparseOpCode : public RegExpOpCode { 457 public: SparseOpCode()458 SparseOpCode() : RegExpOpCode(OP_RANGE32, RegExpOpCode::OP_SIZE_ONE) {} 459 ~SparseOpCode() override = default; 460 NO_COPY_SEMANTIC(SparseOpCode); 461 NO_MOVE_SEMANTIC(SparseOpCode); 462 uint32_t DumpOpCode(std::ostream &out, const DynChunk &buf, uint32_t offset) const override; 463 }; 464 } // namespace ecmascript 465 } // namespace panda 466 #endif 467