| // Copyright 2015 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_WASM_RESULT_H_ |
| #define V8_WASM_RESULT_H_ |
| |
| #include <memory> |
| |
| #include "src/base/compiler-specific.h" |
| |
| #include "src/handles.h" |
| #include "src/globals.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| class Isolate; |
| |
| namespace wasm { |
| |
| // Error codes for programmatic checking of the decoder's verification. |
| enum ErrorCode { |
| kSuccess, |
| kError, // TODO(titzer): introduce real error codes |
| }; |
| |
| // The overall result of decoding a function or a module. |
| template <typename T> |
| struct Result { |
| Result() : val(), error_code(kSuccess), start(nullptr), error_pc(nullptr) {} |
| Result(Result&& other) { *this = std::move(other); } |
| Result& operator=(Result&& other) { |
| MoveFrom(other); |
| val = other.val; |
| return *this; |
| } |
| |
| T val; |
| ErrorCode error_code; |
| const byte* start; |
| const byte* error_pc; |
| const byte* error_pt; |
| std::unique_ptr<char[]> error_msg; |
| |
| bool ok() const { return error_code == kSuccess; } |
| bool failed() const { return error_code != kSuccess; } |
| |
| template <typename V> |
| void MoveFrom(Result<V>& that) { |
| error_code = that.error_code; |
| start = that.start; |
| error_pc = that.error_pc; |
| error_pt = that.error_pt; |
| error_msg = std::move(that.error_msg); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(Result); |
| }; |
| |
| template <typename T> |
| std::ostream& operator<<(std::ostream& os, const Result<T>& result) { |
| os << "Result = "; |
| if (result.ok()) { |
| if (result.val != nullptr) { |
| os << *result.val; |
| } else { |
| os << "success (no value)"; |
| } |
| } else if (result.error_msg.get() != nullptr) { |
| ptrdiff_t offset = result.error_pc - result.start; |
| if (offset < 0) { |
| os << result.error_msg.get() << " @" << offset; |
| } else { |
| os << result.error_msg.get() << " @+" << offset; |
| } |
| } else { |
| os << result.error_code; |
| } |
| os << std::endl; |
| return os; |
| } |
| |
| V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, |
| const ErrorCode& error_code); |
| |
| // A helper for generating error messages that bubble up to JS exceptions. |
| class V8_EXPORT_PRIVATE ErrorThrower { |
| public: |
| ErrorThrower(i::Isolate* isolate, const char* context) |
| : isolate_(isolate), context_(context) {} |
| ~ErrorThrower(); |
| |
| PRINTF_FORMAT(2, 3) void TypeError(const char* fmt, ...); |
| PRINTF_FORMAT(2, 3) void RangeError(const char* fmt, ...); |
| PRINTF_FORMAT(2, 3) void CompileError(const char* fmt, ...); |
| PRINTF_FORMAT(2, 3) void LinkError(const char* fmt, ...); |
| PRINTF_FORMAT(2, 3) void RuntimeError(const char* fmt, ...); |
| |
| template <typename T> |
| void CompileFailed(const char* error, Result<T>& result) { |
| std::ostringstream str; |
| str << error << result; |
| CompileError("%s", str.str().c_str()); |
| } |
| |
| i::Handle<i::Object> Reify() { |
| i::Handle<i::Object> result = exception_; |
| exception_ = i::Handle<i::Object>::null(); |
| return result; |
| } |
| |
| bool error() const { return !exception_.is_null(); } |
| bool wasm_error() { return wasm_error_; } |
| |
| private: |
| void Format(i::Handle<i::JSFunction> constructor, const char* fmt, va_list); |
| |
| i::Isolate* isolate_; |
| const char* context_; |
| i::Handle<i::Object> exception_; |
| bool wasm_error_ = false; |
| }; |
| } // namespace wasm |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif |