// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. #ifndef RUNTIME_VM_EXCEPTIONS_H_ #define RUNTIME_VM_EXCEPTIONS_H_ #include "vm/allocation.h" #include "vm/token_position.h" namespace dart { // Forward declarations. class AbstractType; class Array; class DartFrameIterator; class Error; class LanguageError; class Instance; class Integer; class RawInstance; class RawObject; class RawScript; class RawStackTrace; class String; class Thread; class Exceptions : AllStatic { public: static void Throw(Thread* thread, const Instance& exception); static void ReThrow(Thread* thread, const Instance& exception, const Instance& stacktrace); static void PropagateError(const Error& error); // Propagate an error to the entry frame, skipping over Dart frames. static void PropagateToEntry(const Error& error); // Helpers to create and throw errors. static RawStackTrace* CurrentStackTrace(); static RawScript* GetCallerScript(DartFrameIterator* iterator); static RawInstance* NewInstance(const char* class_name); static void CreateAndThrowTypeError(TokenPosition location, const AbstractType& src_type, const AbstractType& dst_type, const String& dst_name, const String& bound_error_msg); enum ExceptionType { kNone, kRange, kRangeMsg, kArgument, kArgumentValue, kNoSuchMethod, kFormat, kUnsupported, kStackOverflow, kOutOfMemory, kNullThrown, kIsolateSpawn, kAssertion, kCast, kType, kFallThrough, kAbstractClassInstantiation, kCyclicInitializationError, kCompileTimeError, }; static void ThrowByType(ExceptionType type, const Array& arguments); // Uses the preallocated out of memory exception to avoid calling // into Dart code or allocating any code. static void ThrowOOM(); static void ThrowStackOverflow(); static void ThrowArgumentError(const Instance& arg); static void ThrowRangeError(const char* argument_name, const Integer& argument_value, intptr_t expected_from, intptr_t expected_to); static void ThrowRangeErrorMsg(const char* msg); static void ThrowCompileTimeError(const LanguageError& error); // Returns a RawInstance if the exception is successfully created, // otherwise returns a RawError. static RawObject* Create(ExceptionType type, const Array& arguments); static void JumpToFrame(Thread* thread, uword program_counter, uword stack_pointer, uword frame_pointer, bool clear_deopt_at_target); private: DISALLOW_COPY_AND_ASSIGN(Exceptions); }; // The index into the ExceptionHandlers table corresponds to // the try_index of the handler. struct ExceptionHandlerInfo { uint32_t handler_pc_offset; // PC offset value of handler. int16_t outer_try_index; // Try block index of enclosing try block. int8_t needs_stacktrace; // True if a stacktrace is needed. int8_t has_catch_all; // Catches all exceptions. int8_t is_generated; // True if this is a generated handler. }; class CatchEntryState { public: enum { kCatchEntryStateIsMove = 1, kCatchEntryStateDestShift = 1 }; CatchEntryState() : data_(NULL), ref_count_(NULL) {} explicit CatchEntryState(intptr_t* data) : data_(data), ref_count_(new intptr_t(1)) {} CatchEntryState(const CatchEntryState& state) { Copy(state); } ~CatchEntryState() { Destroy(); } CatchEntryState& operator=(const CatchEntryState& state) { Destroy(); Copy(state); return *this; } bool Empty() { return ref_count_ == NULL; } intptr_t Pairs() { return data_[0]; } intptr_t Src(intptr_t i) { return data_[1 + 2 * i]; } intptr_t Dest(intptr_t i) { return data_[2 + 2 * i] >> kCatchEntryStateDestShift; } bool isMove(intptr_t i) { return data_[2 + 2 * i] & kCatchEntryStateIsMove; } private: void Destroy() { if (ref_count_ != NULL) { (*ref_count_)--; if (*ref_count_ == 0) { delete ref_count_; delete[] data_; } } } void Copy(const CatchEntryState& state) { data_ = state.data_; ref_count_ = state.ref_count_; if (ref_count_ != NULL) { (*ref_count_)++; } } // data_ has the following format: // 0 - number of pairs in this state // 1-2 - 1st encoded src,dest pair // 3-4 - 2nd pair // .... intptr_t* data_; intptr_t* ref_count_; }; } // namespace dart #endif // RUNTIME_VM_EXCEPTIONS_H_