Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(541)

Side by Side Diff: src/wasm/decoder.h

Issue 1504713014: Initial import of v8-native WASM. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/ast-decoder.cc ('k') | src/wasm/encoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_DECODER_H_
6 #define V8_WASM_DECODER_H_
7
8 #include "src/base/smart-pointers.h"
9 #include "src/flags.h"
10 #include "src/signature.h"
11 #include "src/wasm/wasm-result.h"
12 #include "src/zone-containers.h"
13
14 namespace v8 {
15 namespace internal {
16 namespace wasm {
17
18 #if DEBUG
19 #define TRACE(...) \
20 do { \
21 if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
22 } while (false)
23 #else
24 #define TRACE(...)
25 #endif
26
27 // A helper utility to decode bytes, integers, fields, varints, etc, from
28 // a buffer of bytes.
29 class Decoder {
30 public:
31 Decoder(const byte* start, const byte* end)
32 : start_(start),
33 pc_(start),
34 limit_(end),
35 error_pc_(nullptr),
36 error_pt_(nullptr) {}
37
38 virtual ~Decoder() {}
39
40 // Reads a 8-bit unsigned integer (byte) and advances {pc_}.
41 uint8_t u8(const char* name = nullptr) {
42 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
43 name ? name : "uint8_t");
44 if (checkAvailable(1)) {
45 byte val = *(pc_++);
46 TRACE("%02x = %d\n", val, val);
47 return val;
48 } else {
49 error("expected 1 byte, but fell off end");
50 return traceOffEnd<uint8_t>();
51 }
52 }
53
54 // Reads a 16-bit unsigned integer (little endian) and advances {pc_}.
55 uint16_t u16(const char* name = nullptr) {
56 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
57 name ? name : "uint16_t");
58 if (checkAvailable(2)) {
59 #ifdef V8_TARGET_LITTLE_ENDIAN
60 byte b0 = pc_[0];
61 byte b1 = pc_[1];
62 #else
63 byte b1 = pc_[0];
64 byte b0 = pc_[1];
65 #endif
66 uint16_t val = static_cast<uint16_t>(b1 << 8) | b0;
67 TRACE("%02x %02x = %d\n", pc_[0], pc_[1], val);
68 pc_ += 2;
69 return val;
70 } else {
71 error("expected 2 bytes, but fell off end");
72 return traceOffEnd<uint16_t>();
73 }
74 }
75
76 // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}.
77 uint32_t u32(const char* name = nullptr) {
78 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
79 name ? name : "uint32_t");
80 if (checkAvailable(4)) {
81 #ifdef V8_TARGET_LITTLE_ENDIAN
82 byte b0 = pc_[0];
83 byte b1 = pc_[1];
84 byte b2 = pc_[2];
85 byte b3 = pc_[3];
86 #else
87 byte b3 = pc_[0];
88 byte b2 = pc_[1];
89 byte b1 = pc_[2];
90 byte b0 = pc_[3];
91 #endif
92 uint32_t val = static_cast<uint32_t>(b3 << 24) |
93 static_cast<uint32_t>(b2 << 16) |
94 static_cast<uint32_t>(b1 << 8) | b0;
95 TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val);
96 pc_ += 4;
97 return val;
98 } else {
99 error("expected 4 bytes, but fell off end");
100 return traceOffEnd<uint32_t>();
101 }
102 }
103
104 // Reads a LEB128 variable-length 32-bit integer and advances {pc_}.
105 uint32_t u32v(int* length, const char* name = nullptr) {
106 TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
107 name ? name : "varint");
108
109 if (!checkAvailable(1)) {
110 error("expected at least 1 byte, but fell off end");
111 return traceOffEnd<uint32_t>();
112 }
113
114 const byte* pos = pc_;
115 const byte* end = pc_ + 5;
116 if (end > limit_) end = limit_;
117
118 uint32_t result = 0;
119 int shift = 0;
120 byte b = 0;
121 while (pc_ < end) {
122 b = *pc_++;
123 TRACE("%02x ", b);
124 result = result | ((b & 0x7F) << shift);
125 if ((b & 0x80) == 0) break;
126 shift += 7;
127 }
128
129 *length = static_cast<int>(pc_ - pos);
130 if (pc_ == end && (b & 0x80)) {
131 error(pc_ - 1, "varint too large");
132 } else {
133 TRACE("= %u\n", result);
134 }
135 return result;
136 }
137
138 // Check that at least {size} bytes exist between {pc_} and {limit_}.
139 bool checkAvailable(int size) {
140 if (pc_ < start_ || (pc_ + size) > limit_) {
141 error(pc_, nullptr, "expected %d bytes, fell off end", size);
142 return false;
143 } else {
144 return true;
145 }
146 }
147
148 void error(const char* msg) { error(pc_, nullptr, msg); }
149
150 void error(const byte* pc, const char* msg) { error(pc, nullptr, msg); }
151
152 // Sets internal error state.
153 void error(const byte* pc, const byte* pt, const char* format, ...) {
154 if (ok()) {
155 #if DEBUG
156 if (FLAG_wasm_break_on_decoder_error) {
157 base::OS::DebugBreak();
158 }
159 #endif
160 const int kMaxErrorMsg = 256;
161 char* buffer = new char[kMaxErrorMsg];
162 va_list arguments;
163 va_start(arguments, format);
164 base::OS::VSNPrintF(buffer, kMaxErrorMsg - 1, format, arguments);
165 va_end(arguments);
166 error_msg_.Reset(buffer);
167 error_pc_ = pc;
168 error_pt_ = pt;
169 onFirstError();
170 }
171 }
172
173 // Behavior triggered on first error, overridden in subclasses.
174 virtual void onFirstError() {}
175
176 // Debugging helper to print bytes up to the end.
177 template <typename T>
178 T traceOffEnd() {
179 T t = 0;
180 for (const byte* ptr = pc_; ptr < limit_; ptr++) {
181 TRACE("%02x ", *ptr);
182 }
183 TRACE("<end>\n");
184 pc_ = limit_;
185 return t;
186 }
187
188 // Converts the given value to a {Result}, copying the error if necessary.
189 template <typename T>
190 Result<T> toResult(T val) {
191 Result<T> result;
192 if (error_pc_) {
193 result.error_code = kError;
194 result.start = start_;
195 result.error_pc = error_pc_;
196 result.error_pt = error_pt_;
197 result.error_msg = error_msg_;
198 error_msg_.Reset(nullptr);
199 } else {
200 result.error_code = kSuccess;
201 result.val = val;
202 }
203 return result;
204 }
205
206 // Resets the boundaries of this decoder.
207 void Reset(const byte* start, const byte* end) {
208 start_ = start;
209 pc_ = start;
210 limit_ = end;
211 error_pc_ = nullptr;
212 error_pt_ = nullptr;
213 error_msg_.Reset(nullptr);
214 }
215
216 bool ok() const { return error_pc_ == nullptr; }
217 bool failed() const { return error_pc_ != nullptr; }
218
219 protected:
220 const byte* start_;
221 const byte* pc_;
222 const byte* limit_;
223 const byte* error_pc_;
224 const byte* error_pt_;
225 base::SmartArrayPointer<char> error_msg_;
226 };
227
228 #undef TRACE
229 } // namespace wasm
230 } // namespace internal
231 } // namespace v8
232
233 #endif // V8_WASM_DECODER_H_
OLDNEW
« no previous file with comments | « src/wasm/ast-decoder.cc ('k') | src/wasm/encoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698