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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/wasm/ast-decoder.cc ('k') | src/wasm/encoder.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/decoder.h
diff --git a/src/wasm/decoder.h b/src/wasm/decoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..df07a6d0ebacf5d463bc622567eace2bdbf9fab6
--- /dev/null
+++ b/src/wasm/decoder.h
@@ -0,0 +1,233 @@
+// 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_DECODER_H_
+#define V8_WASM_DECODER_H_
+
+#include "src/base/smart-pointers.h"
+#include "src/flags.h"
+#include "src/signature.h"
+#include "src/wasm/wasm-result.h"
+#include "src/zone-containers.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+#if DEBUG
+#define TRACE(...) \
+ do { \
+ if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
+ } while (false)
+#else
+#define TRACE(...)
+#endif
+
+// A helper utility to decode bytes, integers, fields, varints, etc, from
+// a buffer of bytes.
+class Decoder {
+ public:
+ Decoder(const byte* start, const byte* end)
+ : start_(start),
+ pc_(start),
+ limit_(end),
+ error_pc_(nullptr),
+ error_pt_(nullptr) {}
+
+ virtual ~Decoder() {}
+
+ // Reads a 8-bit unsigned integer (byte) and advances {pc_}.
+ uint8_t u8(const char* name = nullptr) {
+ TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
+ name ? name : "uint8_t");
+ if (checkAvailable(1)) {
+ byte val = *(pc_++);
+ TRACE("%02x = %d\n", val, val);
+ return val;
+ } else {
+ error("expected 1 byte, but fell off end");
+ return traceOffEnd<uint8_t>();
+ }
+ }
+
+ // Reads a 16-bit unsigned integer (little endian) and advances {pc_}.
+ uint16_t u16(const char* name = nullptr) {
+ TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
+ name ? name : "uint16_t");
+ if (checkAvailable(2)) {
+#ifdef V8_TARGET_LITTLE_ENDIAN
+ byte b0 = pc_[0];
+ byte b1 = pc_[1];
+#else
+ byte b1 = pc_[0];
+ byte b0 = pc_[1];
+#endif
+ uint16_t val = static_cast<uint16_t>(b1 << 8) | b0;
+ TRACE("%02x %02x = %d\n", pc_[0], pc_[1], val);
+ pc_ += 2;
+ return val;
+ } else {
+ error("expected 2 bytes, but fell off end");
+ return traceOffEnd<uint16_t>();
+ }
+ }
+
+ // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}.
+ uint32_t u32(const char* name = nullptr) {
+ TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
+ name ? name : "uint32_t");
+ if (checkAvailable(4)) {
+#ifdef V8_TARGET_LITTLE_ENDIAN
+ byte b0 = pc_[0];
+ byte b1 = pc_[1];
+ byte b2 = pc_[2];
+ byte b3 = pc_[3];
+#else
+ byte b3 = pc_[0];
+ byte b2 = pc_[1];
+ byte b1 = pc_[2];
+ byte b0 = pc_[3];
+#endif
+ uint32_t val = static_cast<uint32_t>(b3 << 24) |
+ static_cast<uint32_t>(b2 << 16) |
+ static_cast<uint32_t>(b1 << 8) | b0;
+ TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val);
+ pc_ += 4;
+ return val;
+ } else {
+ error("expected 4 bytes, but fell off end");
+ return traceOffEnd<uint32_t>();
+ }
+ }
+
+ // Reads a LEB128 variable-length 32-bit integer and advances {pc_}.
+ uint32_t u32v(int* length, const char* name = nullptr) {
+ TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
+ name ? name : "varint");
+
+ if (!checkAvailable(1)) {
+ error("expected at least 1 byte, but fell off end");
+ return traceOffEnd<uint32_t>();
+ }
+
+ const byte* pos = pc_;
+ const byte* end = pc_ + 5;
+ if (end > limit_) end = limit_;
+
+ uint32_t result = 0;
+ int shift = 0;
+ byte b = 0;
+ while (pc_ < end) {
+ b = *pc_++;
+ TRACE("%02x ", b);
+ result = result | ((b & 0x7F) << shift);
+ if ((b & 0x80) == 0) break;
+ shift += 7;
+ }
+
+ *length = static_cast<int>(pc_ - pos);
+ if (pc_ == end && (b & 0x80)) {
+ error(pc_ - 1, "varint too large");
+ } else {
+ TRACE("= %u\n", result);
+ }
+ return result;
+ }
+
+ // Check that at least {size} bytes exist between {pc_} and {limit_}.
+ bool checkAvailable(int size) {
+ if (pc_ < start_ || (pc_ + size) > limit_) {
+ error(pc_, nullptr, "expected %d bytes, fell off end", size);
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ void error(const char* msg) { error(pc_, nullptr, msg); }
+
+ void error(const byte* pc, const char* msg) { error(pc, nullptr, msg); }
+
+ // Sets internal error state.
+ void error(const byte* pc, const byte* pt, const char* format, ...) {
+ if (ok()) {
+#if DEBUG
+ if (FLAG_wasm_break_on_decoder_error) {
+ base::OS::DebugBreak();
+ }
+#endif
+ const int kMaxErrorMsg = 256;
+ char* buffer = new char[kMaxErrorMsg];
+ va_list arguments;
+ va_start(arguments, format);
+ base::OS::VSNPrintF(buffer, kMaxErrorMsg - 1, format, arguments);
+ va_end(arguments);
+ error_msg_.Reset(buffer);
+ error_pc_ = pc;
+ error_pt_ = pt;
+ onFirstError();
+ }
+ }
+
+ // Behavior triggered on first error, overridden in subclasses.
+ virtual void onFirstError() {}
+
+ // Debugging helper to print bytes up to the end.
+ template <typename T>
+ T traceOffEnd() {
+ T t = 0;
+ for (const byte* ptr = pc_; ptr < limit_; ptr++) {
+ TRACE("%02x ", *ptr);
+ }
+ TRACE("<end>\n");
+ pc_ = limit_;
+ return t;
+ }
+
+ // Converts the given value to a {Result}, copying the error if necessary.
+ template <typename T>
+ Result<T> toResult(T val) {
+ Result<T> result;
+ if (error_pc_) {
+ result.error_code = kError;
+ result.start = start_;
+ result.error_pc = error_pc_;
+ result.error_pt = error_pt_;
+ result.error_msg = error_msg_;
+ error_msg_.Reset(nullptr);
+ } else {
+ result.error_code = kSuccess;
+ result.val = val;
+ }
+ return result;
+ }
+
+ // Resets the boundaries of this decoder.
+ void Reset(const byte* start, const byte* end) {
+ start_ = start;
+ pc_ = start;
+ limit_ = end;
+ error_pc_ = nullptr;
+ error_pt_ = nullptr;
+ error_msg_.Reset(nullptr);
+ }
+
+ bool ok() const { return error_pc_ == nullptr; }
+ bool failed() const { return error_pc_ != nullptr; }
+
+ protected:
+ const byte* start_;
+ const byte* pc_;
+ const byte* limit_;
+ const byte* error_pc_;
+ const byte* error_pt_;
+ base::SmartArrayPointer<char> error_msg_;
+};
+
+#undef TRACE
+} // namespace wasm
+} // namespace internal
+} // namespace v8
+
+#endif // V8_WASM_DECODER_H_
« 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