1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_WASM_RESULT_H_
6 #define V8_WASM_RESULT_H_
7 
8 #include <memory>
9 
10 #include "src/base/compiler-specific.h"
11 
12 #include "src/handles.h"
13 #include "src/globals.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 class Isolate;
19 
20 namespace wasm {
21 
22 // Error codes for programmatic checking of the decoder's verification.
23 enum ErrorCode {
24   kSuccess,
25   kError,  // TODO(titzer): introduce real error codes
26 };
27 
28 // The overall result of decoding a function or a module.
29 template <typename T>
30 struct Result {
ResultResult31   Result() : val(), error_code(kSuccess), start(nullptr), error_pc(nullptr) {}
ResultResult32   Result(Result&& other) { *this = std::move(other); }
33   Result& operator=(Result&& other) {
34     MoveFrom(other);
35     val = other.val;
36     return *this;
37   }
38 
39   T val;
40   ErrorCode error_code;
41   const byte* start;
42   const byte* error_pc;
43   const byte* error_pt;
44   std::unique_ptr<char[]> error_msg;
45 
okResult46   bool ok() const { return error_code == kSuccess; }
failedResult47   bool failed() const { return error_code != kSuccess; }
48 
49   template <typename V>
MoveFromResult50   void MoveFrom(Result<V>& that) {
51     error_code = that.error_code;
52     start = that.start;
53     error_pc = that.error_pc;
54     error_pt = that.error_pt;
55     error_msg = std::move(that.error_msg);
56   }
57 
58  private:
59   DISALLOW_COPY_AND_ASSIGN(Result);
60 };
61 
62 template <typename T>
63 std::ostream& operator<<(std::ostream& os, const Result<T>& result) {
64   os << "Result = ";
65   if (result.ok()) {
66     if (result.val != nullptr) {
67       os << *result.val;
68     } else {
69       os << "success (no value)";
70     }
71   } else if (result.error_msg.get() != nullptr) {
72     ptrdiff_t offset = result.error_pc - result.start;
73     if (offset < 0) {
74       os << result.error_msg.get() << " @" << offset;
75     } else {
76       os << result.error_msg.get() << " @+" << offset;
77     }
78   } else {
79     os << result.error_code;
80   }
81   os << std::endl;
82   return os;
83 }
84 
85 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
86                                            const ErrorCode& error_code);
87 
88 // A helper for generating error messages that bubble up to JS exceptions.
89 class V8_EXPORT_PRIVATE ErrorThrower {
90  public:
ErrorThrower(i::Isolate * isolate,const char * context)91   ErrorThrower(i::Isolate* isolate, const char* context)
92       : isolate_(isolate), context_(context) {}
93   ~ErrorThrower();
94 
95   PRINTF_FORMAT(2, 3) void TypeError(const char* fmt, ...);
96   PRINTF_FORMAT(2, 3) void RangeError(const char* fmt, ...);
97   PRINTF_FORMAT(2, 3) void CompileError(const char* fmt, ...);
98   PRINTF_FORMAT(2, 3) void RuntimeError(const char* fmt, ...);
99 
100   template <typename T>
CompileFailed(const char * error,Result<T> & result)101   void CompileFailed(const char* error, Result<T>& result) {
102     std::ostringstream str;
103     str << error << result;
104     CompileError("%s", str.str().c_str());
105   }
106 
Reify()107   i::Handle<i::Object> Reify() {
108     i::Handle<i::Object> result = exception_;
109     exception_ = i::Handle<i::Object>::null();
110     return result;
111   }
112 
error()113   bool error() const { return !exception_.is_null(); }
114 
115  private:
116   void Format(i::Handle<i::JSFunction> constructor, const char* fmt, va_list);
117 
118   i::Isolate* isolate_;
119   const char* context_;
120   i::Handle<i::Object> exception_;
121 };
122 }  // namespace wasm
123 }  // namespace internal
124 }  // namespace v8
125 
126 #endif
127