• 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/base/platform/platform.h"
8 #include "src/base/strings.h"
9 #include "src/execution/isolate-inl.h"
10 #include "src/heap/factory.h"
11 #include "src/heap/heap.h"
12 #include "src/objects/objects.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 =
32         base::VSNPrintF(base::Vector<char>(&str->front() + str_offset,
33                                            static_cast<int>(len - str_offset)),
34                         format, args_copy);
35     va_end(args_copy);
36     if (written < 0) continue;  // not enough space.
37     str->resize(str_offset + written);
38     return;
39   }
40 }
41 
42 PRINTF_FORMAT(3, 4)
PrintFToString(std::string * str,size_t str_offset,const char * format,...)43 void PrintFToString(std::string* str, size_t str_offset, const char* format,
44                     ...) {
45   va_list args;
46   va_start(args, format);
47   VPrintFToString(str, str_offset, format, args);
48   va_end(args);
49 }
50 
51 }  // namespace
52 
53 // static
FormatError(const char * format,va_list args)54 std::string WasmError::FormatError(const char* format, va_list args) {
55   std::string result;
56   VPrintFToString(&result, 0, format, args);
57   return result;
58 }
59 
Format(ErrorType type,const char * format,va_list args)60 void ErrorThrower::Format(ErrorType type, const char* format, va_list args) {
61   DCHECK_NE(kNone, type);
62   // Only report the first error.
63   if (error()) return;
64 
65   size_t context_len = 0;
66   if (context_) {
67     PrintFToString(&error_msg_, 0, "%s: ", context_);
68     context_len = error_msg_.size();
69   }
70   VPrintFToString(&error_msg_, context_len, format, args);
71   error_type_ = type;
72 }
73 
TypeError(const char * format,...)74 void ErrorThrower::TypeError(const char* format, ...) {
75   va_list arguments;
76   va_start(arguments, format);
77   Format(kTypeError, format, arguments);
78   va_end(arguments);
79 }
80 
RangeError(const char * format,...)81 void ErrorThrower::RangeError(const char* format, ...) {
82   va_list arguments;
83   va_start(arguments, format);
84   Format(kRangeError, format, arguments);
85   va_end(arguments);
86 }
87 
CompileError(const char * format,...)88 void ErrorThrower::CompileError(const char* format, ...) {
89   va_list arguments;
90   va_start(arguments, format);
91   Format(kCompileError, format, arguments);
92   va_end(arguments);
93 }
94 
LinkError(const char * format,...)95 void ErrorThrower::LinkError(const char* format, ...) {
96   va_list arguments;
97   va_start(arguments, format);
98   Format(kLinkError, format, arguments);
99   va_end(arguments);
100 }
101 
RuntimeError(const char * format,...)102 void ErrorThrower::RuntimeError(const char* format, ...) {
103   va_list arguments;
104   va_start(arguments, format);
105   Format(kRuntimeError, format, arguments);
106   va_end(arguments);
107 }
108 
Reify()109 Handle<Object> ErrorThrower::Reify() {
110   Handle<JSFunction> constructor;
111   switch (error_type_) {
112     case kNone:
113       UNREACHABLE();
114     case kTypeError:
115       constructor = isolate_->type_error_function();
116       break;
117     case kRangeError:
118       constructor = isolate_->range_error_function();
119       break;
120     case kCompileError:
121       constructor = isolate_->wasm_compile_error_function();
122       break;
123     case kLinkError:
124       constructor = isolate_->wasm_link_error_function();
125       break;
126     case kRuntimeError:
127       constructor = isolate_->wasm_runtime_error_function();
128       break;
129   }
130   Handle<String> message = isolate_->factory()
131                                ->NewStringFromUtf8(base::VectorOf(error_msg_))
132                                .ToHandleChecked();
133   Reset();
134   return isolate_->factory()->NewError(constructor, message);
135 }
136 
Reset()137 void ErrorThrower::Reset() {
138   error_type_ = kNone;
139   error_msg_.clear();
140 }
141 
ErrorThrower(ErrorThrower && other)142 ErrorThrower::ErrorThrower(ErrorThrower&& other) V8_NOEXCEPT
143     : isolate_(other.isolate_),
144       context_(other.context_),
145       error_type_(other.error_type_),
146       error_msg_(std::move(other.error_msg_)) {
147   other.error_type_ = kNone;
148 }
149 
~ErrorThrower()150 ErrorThrower::~ErrorThrower() {
151   if (error() && !isolate_->has_pending_exception()) {
152     // We don't want to mix pending exceptions and scheduled exceptions, hence
153     // an existing exception should be pending, never scheduled.
154     DCHECK(!isolate_->has_scheduled_exception());
155     isolate_->Throw(*Reify());
156   }
157 }
158 
~ScheduledErrorThrower()159 ScheduledErrorThrower::~ScheduledErrorThrower() {
160   // There should never be both a pending and a scheduled exception.
161   DCHECK(!isolate()->has_scheduled_exception() ||
162          !isolate()->has_pending_exception());
163   // Don't throw another error if there is already a scheduled error.
164   if (isolate()->has_scheduled_exception()) {
165     Reset();
166   } else if (isolate()->has_pending_exception()) {
167     Reset();
168     isolate()->OptionalRescheduleException(false);
169   } else if (error()) {
170     isolate()->ScheduleThrow(*Reify());
171   }
172 }
173 
174 }  // namespace wasm
175 }  // namespace internal
176 }  // namespace v8
177