11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_CODEGEN_HANDLER_TABLE_H_
61cb0ef41Sopenharmony_ci#define V8_CODEGEN_HANDLER_TABLE_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/base/bit-field.h"
91cb0ef41Sopenharmony_ci#include "src/common/assert-scope.h"
101cb0ef41Sopenharmony_ci#include "src/common/globals.h"
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_cinamespace v8 {
131cb0ef41Sopenharmony_cinamespace internal {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciclass Assembler;
161cb0ef41Sopenharmony_ciclass ByteArray;
171cb0ef41Sopenharmony_ciclass BytecodeArray;
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cinamespace wasm {
201cb0ef41Sopenharmony_ciclass WasmCode;
211cb0ef41Sopenharmony_ci}  // namespace wasm
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci// HandlerTable is a byte array containing entries for exception handlers in
241cb0ef41Sopenharmony_ci// the code object it is associated with. The tables come in two flavors:
251cb0ef41Sopenharmony_ci// 1) Based on ranges: Used for unoptimized code. Stored in a {ByteArray} that
261cb0ef41Sopenharmony_ci//    is attached to each {BytecodeArray}. Contains one entry per exception
271cb0ef41Sopenharmony_ci//    handler and a range representing the try-block covered by that handler.
281cb0ef41Sopenharmony_ci//    Layout looks as follows:
291cb0ef41Sopenharmony_ci//      [ range-start , range-end , handler-offset , handler-data ]
301cb0ef41Sopenharmony_ci// 2) Based on return addresses: Used for turbofanned code. Stored directly in
311cb0ef41Sopenharmony_ci//    the instruction stream of the {Code} object. Contains one entry per
321cb0ef41Sopenharmony_ci//    call-site that could throw an exception. Layout looks as follows:
331cb0ef41Sopenharmony_ci//      [ return-address-offset , handler-offset ]
341cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE HandlerTable {
351cb0ef41Sopenharmony_ci public:
361cb0ef41Sopenharmony_ci  // Conservative prediction whether a given handler will locally catch an
371cb0ef41Sopenharmony_ci  // exception or cause a re-throw to outside the code boundary. Since this is
381cb0ef41Sopenharmony_ci  // undecidable it is merely an approximation (e.g. useful for debugger).
391cb0ef41Sopenharmony_ci  enum CatchPrediction {
401cb0ef41Sopenharmony_ci    UNCAUGHT,     // The handler will (likely) rethrow the exception.
411cb0ef41Sopenharmony_ci    CAUGHT,       // The exception will be caught by the handler.
421cb0ef41Sopenharmony_ci    PROMISE,      // The exception will be caught and cause a promise rejection.
431cb0ef41Sopenharmony_ci    ASYNC_AWAIT,  // The exception will be caught and cause a promise rejection
441cb0ef41Sopenharmony_ci                  // in the desugaring of an async function, so special
451cb0ef41Sopenharmony_ci                  // async/await handling in the debugger can take place.
461cb0ef41Sopenharmony_ci    UNCAUGHT_ASYNC_AWAIT,  // The exception will be caught and cause a promise
471cb0ef41Sopenharmony_ci                           // rejection in the desugaring of an async REPL
481cb0ef41Sopenharmony_ci                           // script. The corresponding message object needs to
491cb0ef41Sopenharmony_ci                           // be kept alive on the Isolate though.
501cb0ef41Sopenharmony_ci  };
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding };
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  // Constructors for the various encodings.
551cb0ef41Sopenharmony_ci  explicit HandlerTable(Code code);
561cb0ef41Sopenharmony_ci  explicit HandlerTable(ByteArray byte_array);
571cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
581cb0ef41Sopenharmony_ci  explicit HandlerTable(const wasm::WasmCode* code);
591cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
601cb0ef41Sopenharmony_ci  explicit HandlerTable(BytecodeArray bytecode_array);
611cb0ef41Sopenharmony_ci  HandlerTable(Address handler_table, int handler_table_size,
621cb0ef41Sopenharmony_ci               EncodingMode encoding_mode);
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  // Getters for handler table based on ranges.
651cb0ef41Sopenharmony_ci  int GetRangeStart(int index) const;
661cb0ef41Sopenharmony_ci  int GetRangeEnd(int index) const;
671cb0ef41Sopenharmony_ci  int GetRangeHandler(int index) const;
681cb0ef41Sopenharmony_ci  int GetRangeData(int index) const;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  // Setters for handler table based on ranges.
711cb0ef41Sopenharmony_ci  void SetRangeStart(int index, int value);
721cb0ef41Sopenharmony_ci  void SetRangeEnd(int index, int value);
731cb0ef41Sopenharmony_ci  void SetRangeHandler(int index, int offset, CatchPrediction pred);
741cb0ef41Sopenharmony_ci  void SetRangeData(int index, int value);
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  // Returns the required length of the underlying byte array.
771cb0ef41Sopenharmony_ci  static int LengthForRange(int entries);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  // Emitters for handler table based on return addresses.
801cb0ef41Sopenharmony_ci  static int EmitReturnTableStart(Assembler* masm);
811cb0ef41Sopenharmony_ci  static void EmitReturnEntry(Assembler* masm, int offset, int handler);
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  // Lookup handler in a table based on ranges. The {pc_offset} is an offset to
841cb0ef41Sopenharmony_ci  // the start of the potentially throwing instruction (using return addresses
851cb0ef41Sopenharmony_ci  // for this value would be invalid).
861cb0ef41Sopenharmony_ci  int LookupRange(int pc_offset, int* data, CatchPrediction* prediction);
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  // Lookup handler in a table based on return addresses.
891cb0ef41Sopenharmony_ci  int LookupReturn(int pc_offset);
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  // Returns the number of entries in the table.
921cb0ef41Sopenharmony_ci  int NumberOfRangeEntries() const;
931cb0ef41Sopenharmony_ci  int NumberOfReturnEntries() const;
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci#ifdef ENABLE_DISASSEMBLER
961cb0ef41Sopenharmony_ci  void HandlerTableRangePrint(std::ostream& os);
971cb0ef41Sopenharmony_ci  void HandlerTableReturnPrint(std::ostream& os);
981cb0ef41Sopenharmony_ci#endif
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci private:
1011cb0ef41Sopenharmony_ci  // Getters for handler table based on ranges.
1021cb0ef41Sopenharmony_ci  CatchPrediction GetRangePrediction(int index) const;
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci  // Gets entry size based on mode.
1051cb0ef41Sopenharmony_ci  static int EntrySizeFromMode(EncodingMode mode);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  // Getters for handler table based on return addresses.
1081cb0ef41Sopenharmony_ci  int GetReturnOffset(int index) const;
1091cb0ef41Sopenharmony_ci  int GetReturnHandler(int index) const;
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  // Number of entries in the loaded handler table.
1121cb0ef41Sopenharmony_ci  const int number_of_entries_;
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci#ifdef DEBUG
1151cb0ef41Sopenharmony_ci  // The encoding mode of the table. Mostly useful for debugging to check that
1161cb0ef41Sopenharmony_ci  // used accessors and constructors fit together.
1171cb0ef41Sopenharmony_ci  const EncodingMode mode_;
1181cb0ef41Sopenharmony_ci#endif
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  // Direct pointer into the encoded data. This pointer potentially points into
1211cb0ef41Sopenharmony_ci  // objects on the GC heap (either {ByteArray} or {Code}) and could become
1221cb0ef41Sopenharmony_ci  // stale during a collection. Hence we disallow any allocation.
1231cb0ef41Sopenharmony_ci  const Address raw_encoded_data_;
1241cb0ef41Sopenharmony_ci  DISALLOW_GARBAGE_COLLECTION(no_gc_)
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci  // Layout description for handler table based on ranges.
1271cb0ef41Sopenharmony_ci  static const int kRangeStartIndex = 0;
1281cb0ef41Sopenharmony_ci  static const int kRangeEndIndex = 1;
1291cb0ef41Sopenharmony_ci  static const int kRangeHandlerIndex = 2;
1301cb0ef41Sopenharmony_ci  static const int kRangeDataIndex = 3;
1311cb0ef41Sopenharmony_ci  static const int kRangeEntrySize = 4;
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci  // Layout description for handler table based on return addresses.
1341cb0ef41Sopenharmony_ci  static const int kReturnOffsetIndex = 0;
1351cb0ef41Sopenharmony_ci  static const int kReturnHandlerIndex = 1;
1361cb0ef41Sopenharmony_ci  static const int kReturnEntrySize = 2;
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  // Encoding of the {handler} field.
1391cb0ef41Sopenharmony_ci  using HandlerPredictionField = base::BitField<CatchPrediction, 0, 3>;
1401cb0ef41Sopenharmony_ci  using HandlerOffsetField = base::BitField<int, 3, 29>;
1411cb0ef41Sopenharmony_ci};
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci}  // namespace internal
1441cb0ef41Sopenharmony_ci}  // namespace v8
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci#endif  // V8_CODEGEN_HANDLER_TABLE_H_
147