• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/heap/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)
VPrintFToString(std::string & str,size_t str_offset,const char * format,va_list args)21 void VPrintFToString(std::string& str, size_t str_offset, const char* format,
22                      va_list args) {
23   DCHECK_LE(str_offset, str.size());
24   size_t len = str_offset + strlen(format);
25   // Allocate increasingly large buffers until the message fits.
26   for (;; len = base::bits::RoundUpToPowerOfTwo64(len + 1)) {
27     DCHECK_GE(kMaxInt, len);
28     str.resize(len);
29     va_list args_copy;
30     va_copy(args_copy, args);
31     int written = VSNPrintF(Vector<char>(&str.front() + str_offset,
32                                          static_cast<int>(len - str_offset)),
33                             format, args_copy);
34     va_end(args_copy);
35     if (written < 0) continue;  // not enough space.
36     str.resize(str_offset + written);
37     return;
38   }
39 }
40 
41 PRINTF_FORMAT(3, 4)
PrintFToString(std::string & str,size_t str_offset,const char * format,...)42 void PrintFToString(std::string& str, size_t str_offset, const char* format,
43                     ...) {
44   va_list args;
45   va_start(args, format);
46   VPrintFToString(str, str_offset, format, args);
47   va_end(args);
48 }
49 
50 }  // namespace
51 
error(uint32_t offset,std::string error_msg)52 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   error_offset_ = offset;
57   error_msg_ = std::move(error_msg);
58 }
59 
verror(const char * format,va_list args)60 void ResultBase::verror(const char* format, va_list args) {
61   VPrintFToString(error_msg_, 0, format, args);
62   // Assign default message such that ok() and failed() work.
63   if (error_msg_.empty() == 0) error_msg_.assign("Error");
64 }
65 
Format(ErrorType type,const char * format,va_list args)66 void ErrorThrower::Format(ErrorType type, const char* format, va_list args) {
67   DCHECK_NE(kNone, type);
68   // Only report the first error.
69   if (error()) return;
70 
71   size_t context_len = 0;
72   if (context_) {
73     PrintFToString(error_msg_, 0, "%s: ", context_);
74     context_len = error_msg_.size();
75   }
76   VPrintFToString(error_msg_, context_len, format, args);
77   error_type_ = type;
78 }
79 
TypeError(const char * format,...)80 void ErrorThrower::TypeError(const char* format, ...) {
81   va_list arguments;
82   va_start(arguments, format);
83   Format(kTypeError, format, arguments);
84   va_end(arguments);
85 }
86 
RangeError(const char * format,...)87 void ErrorThrower::RangeError(const char* format, ...) {
88   va_list arguments;
89   va_start(arguments, format);
90   Format(kRangeError, format, arguments);
91   va_end(arguments);
92 }
93 
CompileError(const char * format,...)94 void ErrorThrower::CompileError(const char* format, ...) {
95   va_list arguments;
96   va_start(arguments, format);
97   Format(kCompileError, format, arguments);
98   va_end(arguments);
99 }
100 
LinkError(const char * format,...)101 void ErrorThrower::LinkError(const char* format, ...) {
102   va_list arguments;
103   va_start(arguments, format);
104   Format(kLinkError, format, arguments);
105   va_end(arguments);
106 }
107 
RuntimeError(const char * format,...)108 void ErrorThrower::RuntimeError(const char* format, ...) {
109   va_list arguments;
110   va_start(arguments, format);
111   Format(kRuntimeError, format, arguments);
112   va_end(arguments);
113 }
114 
Reify()115 Handle<Object> ErrorThrower::Reify() {
116   Handle<JSFunction> constructor;
117   switch (error_type_) {
118     case kNone:
119       UNREACHABLE();
120     case kTypeError:
121       constructor = isolate_->type_error_function();
122       break;
123     case kRangeError:
124       constructor = isolate_->range_error_function();
125       break;
126     case kCompileError:
127       constructor = isolate_->wasm_compile_error_function();
128       break;
129     case kLinkError:
130       constructor = isolate_->wasm_link_error_function();
131       break;
132     case kRuntimeError:
133       constructor = isolate_->wasm_runtime_error_function();
134       break;
135   }
136   Vector<const char> msg_vec(error_msg_.data(), error_msg_.size());
137   Handle<String> message =
138       isolate_->factory()->NewStringFromUtf8(msg_vec).ToHandleChecked();
139   Reset();
140   return isolate_->factory()->NewError(constructor, message);
141 }
142 
Reset()143 void ErrorThrower::Reset() {
144   error_type_ = kNone;
145   error_msg_.clear();
146 }
147 
ErrorThrower(ErrorThrower && other)148 ErrorThrower::ErrorThrower(ErrorThrower&& other) V8_NOEXCEPT
149     : isolate_(other.isolate_),
150       context_(other.context_),
151       error_type_(other.error_type_),
152       error_msg_(other.error_msg_) {
153   other.error_type_ = kNone;
154 }
155 
~ErrorThrower()156 ErrorThrower::~ErrorThrower() {
157   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     isolate_->Throw(*Reify());
162   }
163 }
164 
165 }  // namespace wasm
166 }  // namespace internal
167 }  // namespace v8
168