Line data Source code
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 : #include "src/wasm/wasm-result.h"
6 :
7 : #include "src/factory.h"
8 : #include "src/heap/heap.h"
9 : #include "src/isolate-inl.h"
10 : #include "src/objects.h"
11 :
12 : #include "src/base/platform/platform.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 : namespace wasm {
17 :
18 : namespace {
19 :
20 : PRINTF_FORMAT(3, 0)
21 49254 : void VPrintFToString(std::string& str, size_t str_offset, const char* format,
22 : va_list args) {
23 : DCHECK_LE(str_offset, str.size());
24 49254 : size_t len = str_offset + strlen(format);
25 : // Allocate increasingly large buffers until the message fits.
26 111619 : for (;; len = base::bits::RoundUpToPowerOfTwo64(len + 1)) {
27 : DCHECK_GE(kMaxInt, len);
28 : str.resize(len);
29 : va_list args_copy;
30 160873 : va_copy(args_copy, args);
31 : int written = VSNPrintF(Vector<char>(&str.front() + str_offset,
32 : static_cast<int>(len - str_offset)),
33 482619 : format, args_copy);
34 160873 : va_end(args_copy);
35 272492 : if (written < 0) continue; // not enough space.
36 49254 : str.resize(str_offset + written);
37 49254 : return;
38 111619 : }
39 : }
40 :
41 : PRINTF_FORMAT(3, 4)
42 24627 : void PrintFToString(std::string& str, size_t str_offset, const char* format,
43 : ...) {
44 : va_list args;
45 24627 : va_start(args, format);
46 24627 : VPrintFToString(str, str_offset, format, args);
47 24627 : va_end(args);
48 24627 : }
49 :
50 : } // namespace
51 :
52 41339 : void ResultBase::error(uint32_t offset, std::string error_msg) {
53 : // The error message must not be empty, otherwise Result::failed() will be
54 : // false.
55 : DCHECK(!error_msg.empty());
56 41339 : error_offset_ = offset;
57 41339 : error_msg_ = std::move(error_msg);
58 41339 : }
59 :
60 0 : void ResultBase::verror(const char* format, va_list args) {
61 0 : VPrintFToString(error_msg_, 0, format, args);
62 : // Assign default message such that ok() and failed() work.
63 0 : if (error_msg_.empty() == 0) error_msg_.assign("Error");
64 0 : }
65 :
66 30704 : void ErrorThrower::Format(ErrorType type, const char* format, va_list args) {
67 : DCHECK_NE(kNone, type);
68 : // Only report the first error.
69 61408 : if (error()) return;
70 :
71 : size_t context_len = 0;
72 24627 : if (context_) {
73 24627 : PrintFToString(error_msg_, 0, "%s: ", context_);
74 : context_len = error_msg_.size();
75 : }
76 24627 : VPrintFToString(error_msg_, context_len, format, args);
77 24627 : error_type_ = type;
78 : }
79 :
80 9085 : void ErrorThrower::TypeError(const char* format, ...) {
81 : va_list arguments;
82 9085 : va_start(arguments, format);
83 9085 : Format(kTypeError, format, arguments);
84 9085 : va_end(arguments);
85 9085 : }
86 :
87 1290 : void ErrorThrower::RangeError(const char* format, ...) {
88 : va_list arguments;
89 1290 : va_start(arguments, format);
90 1290 : Format(kRangeError, format, arguments);
91 1290 : va_end(arguments);
92 1290 : }
93 :
94 18866 : void ErrorThrower::CompileError(const char* format, ...) {
95 : va_list arguments;
96 18866 : va_start(arguments, format);
97 18866 : Format(kCompileError, format, arguments);
98 18866 : va_end(arguments);
99 18866 : }
100 :
101 1403 : void ErrorThrower::LinkError(const char* format, ...) {
102 : va_list arguments;
103 1403 : va_start(arguments, format);
104 1403 : Format(kLinkError, format, arguments);
105 1403 : va_end(arguments);
106 1403 : }
107 :
108 60 : void ErrorThrower::RuntimeError(const char* format, ...) {
109 : va_list arguments;
110 60 : va_start(arguments, format);
111 60 : Format(kRuntimeError, format, arguments);
112 60 : va_end(arguments);
113 60 : }
114 :
115 24534 : Handle<Object> ErrorThrower::Reify() {
116 : Handle<JSFunction> constructor;
117 24534 : switch (error_type_) {
118 : case kNone:
119 0 : UNREACHABLE();
120 : case kTypeError:
121 9067 : constructor = isolate_->type_error_function();
122 9067 : break;
123 : case kRangeError:
124 1290 : constructor = isolate_->range_error_function();
125 1290 : break;
126 : case kCompileError:
127 12945 : constructor = isolate_->wasm_compile_error_function();
128 12945 : break;
129 : case kLinkError:
130 1172 : constructor = isolate_->wasm_link_error_function();
131 1172 : break;
132 : case kRuntimeError:
133 60 : constructor = isolate_->wasm_runtime_error_function();
134 60 : break;
135 : }
136 : Vector<const char> msg_vec(error_msg_.data(), error_msg_.size());
137 : Handle<String> message =
138 49068 : isolate_->factory()->NewStringFromUtf8(msg_vec).ToHandleChecked();
139 : Reset();
140 24534 : return isolate_->factory()->NewError(constructor, message);
141 : }
142 :
143 1609 : void ErrorThrower::Reset() {
144 26143 : error_type_ = kNone;
145 26143 : error_msg_.clear();
146 1609 : }
147 :
148 0 : ErrorThrower::ErrorThrower(ErrorThrower&& other)
149 : : isolate_(other.isolate_),
150 : context_(other.context_),
151 : error_type_(other.error_type_),
152 0 : error_msg_(other.error_msg_) {
153 0 : other.error_type_ = kNone;
154 0 : }
155 :
156 26955645 : ErrorThrower::~ErrorThrower() {
157 26955645 : if (error() && !isolate_->has_pending_exception()) {
158 : // We don't want to mix pending exceptions and scheduled exceptions, hence
159 : // an existing exception should be pending, never scheduled.
160 : DCHECK(!isolate_->has_scheduled_exception());
161 172 : isolate_->Throw(*Reify());
162 : }
163 26955645 : }
164 :
165 : } // namespace wasm
166 : } // namespace internal
167 : } // namespace v8
|