2018-02-27 09:23:48 +00:00
|
|
|
// Copyright 2018 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
#ifndef V8_HANDLER_TABLE_H_
|
|
|
|
#define V8_HANDLER_TABLE_H_
|
|
|
|
|
|
|
|
#include "src/assert-scope.h"
|
|
|
|
#include "src/globals.h"
|
|
|
|
#include "src/utils.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
class Assembler;
|
|
|
|
class ByteArray;
|
|
|
|
class BytecodeArray;
|
|
|
|
|
|
|
|
// HandlerTable is a byte array containing entries for exception handlers in
|
|
|
|
// the code object it is associated with. The tables come in two flavors:
|
|
|
|
// 1) Based on ranges: Used for unoptimized code. Stored in a {ByteArray} that
|
|
|
|
// is attached to each {BytecodeArray}. Contains one entry per exception
|
|
|
|
// handler and a range representing the try-block covered by that handler.
|
|
|
|
// Layout looks as follows:
|
|
|
|
// [ range-start , range-end , handler-offset , handler-data ]
|
|
|
|
// 2) Based on return addresses: Used for turbofanned code. Stored directly in
|
|
|
|
// the instruction stream of the {Code} object. Contains one entry per
|
|
|
|
// call-site that could throw an exception. Layout looks as follows:
|
|
|
|
// [ return-address-offset , handler-offset ]
|
|
|
|
class V8_EXPORT_PRIVATE HandlerTable {
|
|
|
|
public:
|
|
|
|
// Conservative prediction whether a given handler will locally catch an
|
|
|
|
// exception or cause a re-throw to outside the code boundary. Since this is
|
|
|
|
// undecidable it is merely an approximation (e.g. useful for debugger).
|
|
|
|
enum CatchPrediction {
|
|
|
|
UNCAUGHT, // The handler will (likely) rethrow the exception.
|
|
|
|
CAUGHT, // The exception will be caught by the handler.
|
|
|
|
PROMISE, // The exception will be caught and cause a promise rejection.
|
|
|
|
DESUGARING, // The exception will be caught, but both the exception and
|
|
|
|
// the catching are part of a desugaring and should therefore
|
|
|
|
// not be visible to the user (we won't notify the debugger of
|
|
|
|
// such exceptions).
|
|
|
|
ASYNC_AWAIT, // The exception will be caught and cause a promise rejection
|
|
|
|
// in the desugaring of an async function, so special
|
|
|
|
// async/await handling in the debugger can take place.
|
|
|
|
};
|
|
|
|
|
|
|
|
// Constructors for the various encodings.
|
2018-11-08 21:42:34 +00:00
|
|
|
explicit HandlerTable(Code code);
|
2018-11-24 08:51:21 +00:00
|
|
|
explicit HandlerTable(ByteArray byte_array);
|
2018-11-24 09:49:54 +00:00
|
|
|
explicit HandlerTable(BytecodeArray bytecode_array);
|
2018-02-27 09:23:48 +00:00
|
|
|
explicit HandlerTable(Address instruction_start, size_t handler_table_offset);
|
|
|
|
|
|
|
|
// Getters for handler table based on ranges.
|
|
|
|
int GetRangeStart(int index) const;
|
|
|
|
int GetRangeEnd(int index) const;
|
|
|
|
int GetRangeHandler(int index) const;
|
|
|
|
int GetRangeData(int index) const;
|
|
|
|
|
|
|
|
// Setters for handler table based on ranges.
|
|
|
|
void SetRangeStart(int index, int value);
|
|
|
|
void SetRangeEnd(int index, int value);
|
|
|
|
void SetRangeHandler(int index, int offset, CatchPrediction pred);
|
|
|
|
void SetRangeData(int index, int value);
|
|
|
|
|
|
|
|
// Returns the required length of the underlying byte array.
|
|
|
|
static int LengthForRange(int entries);
|
|
|
|
|
|
|
|
// Emitters for handler table based on return addresses.
|
|
|
|
static int EmitReturnTableStart(Assembler* masm, int entries);
|
|
|
|
static void EmitReturnEntry(Assembler* masm, int offset, int handler);
|
|
|
|
|
|
|
|
// Lookup handler in a table based on ranges. The {pc_offset} is an offset to
|
|
|
|
// the start of the potentially throwing instruction (using return addresses
|
|
|
|
// for this value would be invalid).
|
|
|
|
int LookupRange(int pc_offset, int* data, CatchPrediction* prediction);
|
|
|
|
|
|
|
|
// Lookup handler in a table based on return addresses.
|
|
|
|
int LookupReturn(int pc_offset);
|
|
|
|
|
|
|
|
// Returns the number of entries in the table.
|
|
|
|
int NumberOfRangeEntries() const;
|
|
|
|
int NumberOfReturnEntries() const;
|
|
|
|
|
|
|
|
#ifdef ENABLE_DISASSEMBLER
|
|
|
|
void HandlerTableRangePrint(std::ostream& os); // NOLINT
|
|
|
|
void HandlerTableReturnPrint(std::ostream& os); // NOLINT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
private:
|
|
|
|
enum EncodingMode { kRangeBasedEncoding, kReturnAddressBasedEncoding };
|
|
|
|
|
|
|
|
// Getters for handler table based on ranges.
|
|
|
|
CatchPrediction GetRangePrediction(int index) const;
|
|
|
|
|
|
|
|
// Getters for handler table based on return addresses.
|
|
|
|
int GetReturnOffset(int index) const;
|
|
|
|
int GetReturnHandler(int index) const;
|
|
|
|
|
|
|
|
// Number of entries in the loaded handler table.
|
|
|
|
int number_of_entries_;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
// The encoding mode of the table. Mostly useful for debugging to check that
|
|
|
|
// used accessors and constructors fit together.
|
|
|
|
EncodingMode mode_;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Direct pointer into the encoded data. This pointer points into object on
|
|
|
|
// the GC heap (either {ByteArray} or {Code}) and hence would become stale
|
|
|
|
// during a collection. Hence we disallow any allocation.
|
|
|
|
Address raw_encoded_data_;
|
2018-10-15 08:41:39 +00:00
|
|
|
DISALLOW_HEAP_ALLOCATION(no_gc_);
|
2018-02-27 09:23:48 +00:00
|
|
|
|
|
|
|
// Layout description for handler table based on ranges.
|
|
|
|
static const int kRangeStartIndex = 0;
|
|
|
|
static const int kRangeEndIndex = 1;
|
|
|
|
static const int kRangeHandlerIndex = 2;
|
|
|
|
static const int kRangeDataIndex = 3;
|
|
|
|
static const int kRangeEntrySize = 4;
|
|
|
|
|
|
|
|
// Layout description for handler table based on return addresses.
|
|
|
|
static const int kReturnOffsetIndex = 0;
|
|
|
|
static const int kReturnHandlerIndex = 1;
|
|
|
|
static const int kReturnEntrySize = 2;
|
|
|
|
|
|
|
|
// Encoding of the {handler} field.
|
|
|
|
class HandlerPredictionField : public BitField<CatchPrediction, 0, 3> {};
|
|
|
|
class HandlerOffsetField : public BitField<int, 3, 29> {};
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_HANDLER_TABLE_H_
|