Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
exceptions.h
Go to the documentation of this file.
1// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_EXCEPTIONS_H_
6#define RUNTIME_VM_EXCEPTIONS_H_
7
8#include "vm/allocation.h"
9#include "vm/bitfield.h"
10#include "vm/tagged_pointer.h"
11#include "vm/token_position.h"
12
13namespace dart {
14
15// Forward declarations.
16class AbstractType;
17class Array;
18class DartFrameIterator;
19class Error;
20class LanguageError;
21class Instance;
22class Integer;
23class ReadStream;
24class BaseWriteStream;
25class String;
26class Thread;
27class TypedData;
28
30 public:
31 DART_NORETURN static void Throw(Thread* thread, const Instance& exception);
32 DART_NORETURN static void ReThrow(Thread* thread,
33 const Instance& exception,
34 const Instance& stacktrace,
35 bool bypass_debugger = false);
36 DART_NORETURN static void ThrowWithStackTrace(Thread* thread,
37 const Instance& exception,
38 const Instance& stacktrace);
39 DART_NORETURN static void PropagateError(const Error& error);
40
41 // Propagate an error to the entry frame, skipping over Dart frames.
42 DART_NORETURN static void PropagateToEntry(const Error& error);
43
44 // Helpers to create and throw errors.
45 static StackTracePtr CurrentStackTrace();
46 static ScriptPtr GetCallerScript(DartFrameIterator* iterator);
47 static InstancePtr NewInstance(const char* class_name);
48 static void CreateAndThrowTypeError(TokenPosition location,
49 const AbstractType& src_type,
50 const AbstractType& dst_type,
51 const String& dst_name);
52
75
76 DART_NORETURN static void ThrowByType(ExceptionType type,
77 const Array& arguments);
78 // Uses the preallocated out of memory exception to avoid calling
79 // into Dart code or allocating any code.
80 DART_NORETURN static void ThrowOOM();
81 DART_NORETURN static void ThrowStackOverflow();
82 DART_NORETURN static void ThrowArgumentError(const Instance& arg);
83 DART_NORETURN static void ThrowStateError(const Instance& arg);
84 DART_NORETURN static void ThrowRangeError(const char* argument_name,
85 const Integer& argument_value,
86 intptr_t expected_from,
87 intptr_t expected_to);
88 DART_NORETURN static void ThrowUnsupportedError(const char* msg);
89 DART_NORETURN static void ThrowCompileTimeError(const LanguageError& error);
90 DART_NORETURN static void ThrowLateFieldAssignedDuringInitialization(
91 const String& name);
92 DART_NORETURN static void ThrowLateFieldNotInitialized(const String& name);
93
94 // Returns an InstancePtr if the exception is successfully created,
95 // otherwise returns an ErrorPtr.
96 static ObjectPtr Create(ExceptionType type, const Array& arguments);
97
98 // Returns RawUnhandledException that wraps exception of type [type] with
99 // [msg] as a single argument.
100 static UnhandledExceptionPtr CreateUnhandledException(Zone* zone,
102 const char* msg);
103
104 DART_NORETURN static void JumpToFrame(Thread* thread,
105 uword program_counter,
106 uword stack_pointer,
107 uword frame_pointer,
108 bool clear_deopt_at_target);
109
110 private:
112};
113
114// The index into the ExceptionHandlers table corresponds to
115// the try_index of the handler.
117 uint32_t handler_pc_offset; // PC offset value of handler.
118 int16_t outer_try_index; // Try block index of enclosing try block.
119 int8_t needs_stacktrace; // True if a stacktrace is needed.
120 int8_t has_catch_all; // Catches all exceptions.
121 int8_t is_generated; // True if this is a generated handler.
122};
123
124//
125// Support for try/catch in the optimized code.
126//
127// Optimizing compiler does not model exceptional control flow explicitly,
128// instead we rely on the runtime system to create correct state at the
129// entry into the catch block by reshuffling values in the frame into
130// positions where they are expected to be at the beginning of the catch block.
131//
132// See runtime/docs/compiler/exceptions.md for more details.
133//
134
135// A single move from a stack slot or an object pool into another stack slot.
136// Destination slot is expecting only tagged values, however source
137// slot can contain an unboxed value (e.g. an unboxed double) - in this case
138// we will box the value before executing the move.
140 public:
142 : src_(0),
143 dest_and_kind_(static_cast<intptr_t>(SourceKind::kTaggedSlot)) {
145 }
146
160
162 return SourceKindField::decode(dest_and_kind_);
163 }
164
165 intptr_t src_slot() const {
167 return src_;
168 }
169
170 intptr_t src_lo_slot() const {
172 return index_to_pair_slot(LoSourceSlot::decode(src_));
173 }
174
175 intptr_t src_hi_slot() const {
177 return index_to_pair_slot(HiSourceSlot::decode(src_));
178 }
179
180 intptr_t dest_slot() const {
181 return dest_and_kind_ >> SourceKindField::bitsize();
182 }
183
184 static CatchEntryMove FromConstant(intptr_t pool_id, intptr_t dest_slot) {
185 return FromSlot(SourceKind::kConstant, pool_id, dest_slot);
186 }
187
189 intptr_t src_slot,
190 intptr_t dest_slot) {
192 (static_cast<uintptr_t>(dest_slot)
194 }
195
196 static intptr_t EncodePairSource(intptr_t src_lo_slot, intptr_t src_hi_slot) {
197 return LoSourceSlot::encode(pair_slot_to_index(src_lo_slot)) |
198 HiSourceSlot::encode(pair_slot_to_index(src_hi_slot));
199 }
200
201 bool IsRedundant() const {
202 return (source_kind() == SourceKind::kTaggedSlot) &&
203 (dest_slot() == src_slot());
204 }
205
206 bool operator==(const CatchEntryMove& rhs) const {
207 return src_ == rhs.src_ && dest_and_kind_ == rhs.dest_and_kind_;
208 }
209
210 static CatchEntryMove ReadFrom(ReadStream* stream);
211
212#if !defined(DART_PRECOMPILED_RUNTIME)
213 void WriteTo(BaseWriteStream* stream);
214#endif
215
216#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
217 const char* ToCString() const;
218#endif
219
220 private:
221 static intptr_t pair_slot_to_index(intptr_t slot) {
222 return (slot < 0) ? -2 * slot : 2 * slot + 1;
223 }
224
225 static intptr_t index_to_pair_slot(intptr_t index) {
226 ASSERT(index >= 0);
227 return ((index & 1) != 0) ? (index >> 1) : -(index >> 1);
228 }
229
230 CatchEntryMove(int32_t src, int32_t dest_and_kind)
231 : src_(src), dest_and_kind_(dest_and_kind) {}
232
233 // Note: BitField helper does not work with signed values of size that does
234 // not match the destination size - thus we don't use BitField for declaring
235 // DestinationField and instead encode and decode it manually.
236 using SourceKindField = BitField<int32_t, SourceKind, 0, 4>;
237
238 static constexpr intptr_t kHalfSourceBits = 16;
239 using LoSourceSlot = BitField<int32_t, int32_t, 0, kHalfSourceBits>;
240 using HiSourceSlot =
241 BitField<int32_t, int32_t, kHalfSourceBits, kHalfSourceBits>;
242
243 int32_t src_;
244 int32_t dest_and_kind_;
245};
246
247// A sequence of moves that needs to be executed to create a state expected
248// at the catch entry.
249// Note: this is a deserialized representation that is used by the runtime
250// system as a temporary representation and for caching. That is why this
251// object is allocated in the mallocated heap and not in the Dart heap.
253 public:
254 static CatchEntryMoves* Allocate(intptr_t num_moves) {
255 auto result = reinterpret_cast<CatchEntryMoves*>(
256 malloc(sizeof(CatchEntryMoves) + sizeof(CatchEntryMove) * num_moves));
257 result->count_ = num_moves;
258 return result;
259 }
260
261 static void Free(const CatchEntryMoves* moves) {
262 free(const_cast<CatchEntryMoves*>(moves));
263 }
264
265 intptr_t count() const { return count_; }
266 CatchEntryMove& At(intptr_t i) { return Moves()[i]; }
267 const CatchEntryMove& At(intptr_t i) const { return Moves()[i]; }
268
269 private:
270 CatchEntryMove* Moves() {
271 return reinterpret_cast<CatchEntryMove*>(this + 1);
272 }
273
274 const CatchEntryMove* Moves() const {
275 return reinterpret_cast<const CatchEntryMove*>(this + 1);
276 }
277
278 intptr_t count_;
279 // Followed by CatchEntryMove[count_]
280};
281
282// Used for reading the [CatchEntryMoves] from the compressed form.
284 public:
285 explicit CatchEntryMovesMapReader(const TypedData& bytes) : bytes_(bytes) {}
286
287 // The returned [CatchEntryMoves] must be freed by the caller via [free].
288 CatchEntryMoves* ReadMovesForPcOffset(intptr_t pc_offset);
289
290#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
291 void PrintEntries();
292#endif
293
294 private:
295 // Given the [pc_offset] this function will find the [position] at which to
296 // read the catch entries and the [length] of the catch entry moves array.
297 void FindEntryForPc(ReadStream* stream,
298 intptr_t pc_offset,
299 intptr_t* position,
300 intptr_t* length);
301
302 // Reads the [length] catch entry moves from [offset] in the [stream].
303 CatchEntryMoves* ReadCompressedCatchEntryMovesSuffix(ReadStream* stream,
304 intptr_t offset,
305 intptr_t length);
306
307 const TypedData& bytes_;
308};
309
310// A simple reference counting wrapper for CatchEntryMoves.
311//
312// TODO(vegorov) switch this to intrusive reference counting.
314 public:
315 CatchEntryMovesRefPtr() : moves_(nullptr), ref_count_(nullptr) {}
317 : moves_(moves), ref_count_(new intptr_t(1)) {}
318
320
321 ~CatchEntryMovesRefPtr() { Destroy(); }
322
324 Destroy();
325 Copy(state);
326 return *this;
327 }
328
329 bool IsEmpty() { return ref_count_ == nullptr; }
330
331 const CatchEntryMoves& moves() { return *moves_; }
332
333 private:
334 void Destroy() {
335 if (ref_count_ != nullptr) {
336 (*ref_count_)--;
337 if (*ref_count_ == 0) {
338 delete ref_count_;
339 CatchEntryMoves::Free(moves_);
340 }
341 }
342 }
343
344 void Copy(const CatchEntryMovesRefPtr& state) {
345 moves_ = state.moves_;
346 ref_count_ = state.ref_count_;
347 if (ref_count_ != nullptr) {
348 (*ref_count_)++;
349 }
350 }
351
352 const CatchEntryMoves* moves_;
353 intptr_t* ref_count_;
354};
355
356} // namespace dart
357
358#endif // RUNTIME_VM_EXCEPTIONS_H_
static sk_sp< Effect > Create()
static constexpr int bitsize()
Definition bitfield.h:164
static constexpr T decode(S value)
Definition bitfield.h:173
static constexpr S encode(T value)
Definition bitfield.h:167
intptr_t dest_slot() const
Definition exceptions.h:180
static CatchEntryMove FromSlot(SourceKind kind, intptr_t src_slot, intptr_t dest_slot)
Definition exceptions.h:188
static CatchEntryMove FromConstant(intptr_t pool_id, intptr_t dest_slot)
Definition exceptions.h:184
intptr_t src_hi_slot() const
Definition exceptions.h:175
const char * ToCString() const
static intptr_t EncodePairSource(intptr_t src_lo_slot, intptr_t src_hi_slot)
Definition exceptions.h:196
bool operator==(const CatchEntryMove &rhs) const
Definition exceptions.h:206
bool IsRedundant() const
Definition exceptions.h:201
void WriteTo(BaseWriteStream *stream)
intptr_t src_slot() const
Definition exceptions.h:165
SourceKind source_kind() const
Definition exceptions.h:161
static CatchEntryMove ReadFrom(ReadStream *stream)
intptr_t src_lo_slot() const
Definition exceptions.h:170
CatchEntryMoves * ReadMovesForPcOffset(intptr_t pc_offset)
CatchEntryMovesMapReader(const TypedData &bytes)
Definition exceptions.h:285
CatchEntryMovesRefPtr(const CatchEntryMovesRefPtr &state)
Definition exceptions.h:319
const CatchEntryMoves & moves()
Definition exceptions.h:331
CatchEntryMovesRefPtr & operator=(const CatchEntryMovesRefPtr &state)
Definition exceptions.h:323
CatchEntryMovesRefPtr(const CatchEntryMoves *moves)
Definition exceptions.h:316
const CatchEntryMove & At(intptr_t i) const
Definition exceptions.h:267
intptr_t count() const
Definition exceptions.h:265
static void Free(const CatchEntryMoves *moves)
Definition exceptions.h:261
static CatchEntryMoves * Allocate(intptr_t num_moves)
Definition exceptions.h:254
CatchEntryMove & At(intptr_t i)
Definition exceptions.h:266
static DART_NORETURN void ThrowStateError(const Instance &arg)
static DART_NORETURN void ThrowStackOverflow()
static DART_NORETURN void JumpToFrame(Thread *thread, uword program_counter, uword stack_pointer, uword frame_pointer, bool clear_deopt_at_target)
static DART_NORETURN void ThrowByType(ExceptionType type, const Array &arguments)
static DART_NORETURN void ThrowOOM()
static DART_NORETURN void ThrowRangeError(const char *argument_name, const Integer &argument_value, intptr_t expected_from, intptr_t expected_to)
static DART_NORETURN void ThrowUnsupportedError(const char *msg)
static InstancePtr NewInstance(const char *class_name)
static DART_NORETURN void ThrowLateFieldAssignedDuringInitialization(const String &name)
static DART_NORETURN void Throw(Thread *thread, const Instance &exception)
static DART_NORETURN void ThrowArgumentError(const Instance &arg)
static DART_NORETURN void PropagateToEntry(const Error &error)
static ScriptPtr GetCallerScript(DartFrameIterator *iterator)
@ kAbstractClassInstantiation
Definition exceptions.h:69
@ kLateFieldAssignedDuringInitialization
Definition exceptions.h:72
@ kIntegerDivisionByZeroException
Definition exceptions.h:60
static StackTracePtr CurrentStackTrace()
static DART_NORETURN void ThrowLateFieldNotInitialized(const String &name)
static DART_NORETURN void ThrowCompileTimeError(const LanguageError &error)
static UnhandledExceptionPtr CreateUnhandledException(Zone *zone, ExceptionType type, const char *msg)
static DART_NORETURN void ReThrow(Thread *thread, const Instance &exception, const Instance &stacktrace, bool bypass_debugger=false)
static void CreateAndThrowTypeError(TokenPosition location, const AbstractType &src_type, const AbstractType &dst_type, const String &dst_name)
static DART_NORETURN void ThrowWithStackTrace(Thread *thread, const Instance &exception, const Instance &stacktrace)
static DART_NORETURN void PropagateError(const Error &error)
#define ASSERT(E)
AtkStateType state
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
size_t length
const char *const name
void * malloc(size_t size)
Definition allocation.cc:19
const char *const class_name
uintptr_t uword
Definition globals.h:501
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
Point offset