OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/execution.h" | 5 #include "src/execution.h" |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" | 9 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 PrintF(": %s", String::cast(name)->ToCString().get()); | 47 PrintF(": %s", String::cast(name)->ToCString().get()); |
48 } | 48 } |
49 } | 49 } |
50 PrintF("]\n"); | 50 PrintF("]\n"); |
51 } | 51 } |
52 } | 52 } |
53 | 53 |
54 | 54 |
55 namespace { | 55 namespace { |
56 | 56 |
| 57 enum class MessageHandling { kReport, kKeep }; |
| 58 |
57 MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, | 59 MUST_USE_RESULT MaybeHandle<Object> Invoke(Isolate* isolate, bool is_construct, |
58 Handle<Object> target, | 60 Handle<Object> target, |
59 Handle<Object> receiver, int argc, | 61 Handle<Object> receiver, int argc, |
60 Handle<Object> args[], | 62 Handle<Object> args[], |
61 Handle<Object> new_target) { | 63 Handle<Object> new_target, |
| 64 MessageHandling message_handling) { |
62 DCHECK(!receiver->IsJSGlobalObject()); | 65 DCHECK(!receiver->IsJSGlobalObject()); |
63 | 66 |
64 #ifdef USE_SIMULATOR | 67 #ifdef USE_SIMULATOR |
65 // Simulators use separate stacks for C++ and JS. JS stack overflow checks | 68 // Simulators use separate stacks for C++ and JS. JS stack overflow checks |
66 // are performed whenever a JS function is called. However, it can be the case | 69 // are performed whenever a JS function is called. However, it can be the case |
67 // that the C++ stack grows faster than the JS stack, resulting in an overflow | 70 // that the C++ stack grows faster than the JS stack, resulting in an overflow |
68 // there. Add a check here to make that less likely. | 71 // there. Add a check here to make that less likely. |
69 StackLimitCheck check(isolate); | 72 StackLimitCheck check(isolate); |
70 if (check.HasOverflowed()) { | 73 if (check.HasOverflowed()) { |
71 isolate->StackOverflow(); | 74 isolate->StackOverflow(); |
72 isolate->ReportPendingMessages(); | 75 if (message_handling == MessageHandling::kReport) { |
| 76 isolate->ReportPendingMessages(); |
| 77 } |
73 return MaybeHandle<Object>(); | 78 return MaybeHandle<Object>(); |
74 } | 79 } |
75 #endif | 80 #endif |
76 | 81 |
77 // api callbacks can be called directly. | 82 // api callbacks can be called directly. |
78 if (target->IsJSFunction()) { | 83 if (target->IsJSFunction()) { |
79 Handle<JSFunction> function = Handle<JSFunction>::cast(target); | 84 Handle<JSFunction> function = Handle<JSFunction>::cast(target); |
80 if ((!is_construct || function->IsConstructor()) && | 85 if ((!is_construct || function->IsConstructor()) && |
81 function->shared()->IsApiFunction()) { | 86 function->shared()->IsApiFunction()) { |
82 SaveContext save(isolate); | 87 SaveContext save(isolate); |
83 isolate->set_context(function->context()); | 88 isolate->set_context(function->context()); |
84 DCHECK(function->context()->global_object()->IsJSGlobalObject()); | 89 DCHECK(function->context()->global_object()->IsJSGlobalObject()); |
85 if (is_construct) receiver = isolate->factory()->the_hole_value(); | 90 if (is_construct) receiver = isolate->factory()->the_hole_value(); |
86 auto value = Builtins::InvokeApiFunction( | 91 auto value = Builtins::InvokeApiFunction( |
87 isolate, is_construct, function, receiver, argc, args, | 92 isolate, is_construct, function, receiver, argc, args, |
88 Handle<HeapObject>::cast(new_target)); | 93 Handle<HeapObject>::cast(new_target)); |
89 bool has_exception = value.is_null(); | 94 bool has_exception = value.is_null(); |
90 DCHECK(has_exception == isolate->has_pending_exception()); | 95 DCHECK(has_exception == isolate->has_pending_exception()); |
91 if (has_exception) { | 96 if (has_exception) { |
92 isolate->ReportPendingMessages(); | 97 if (message_handling == MessageHandling::kReport) { |
| 98 isolate->ReportPendingMessages(); |
| 99 } |
93 return MaybeHandle<Object>(); | 100 return MaybeHandle<Object>(); |
94 } else { | 101 } else { |
95 isolate->clear_pending_message(); | 102 isolate->clear_pending_message(); |
96 } | 103 } |
97 return value; | 104 return value; |
98 } | 105 } |
99 } | 106 } |
100 | 107 |
101 // Entering JavaScript. | 108 // Entering JavaScript. |
102 VMState<JS> state(isolate); | 109 VMState<JS> state(isolate); |
103 CHECK(AllowJavascriptExecution::IsAllowed(isolate)); | 110 CHECK(AllowJavascriptExecution::IsAllowed(isolate)); |
104 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { | 111 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { |
105 isolate->ThrowIllegalOperation(); | 112 isolate->ThrowIllegalOperation(); |
106 isolate->ReportPendingMessages(); | 113 if (message_handling == MessageHandling::kReport) { |
| 114 isolate->ReportPendingMessages(); |
| 115 } |
107 return MaybeHandle<Object>(); | 116 return MaybeHandle<Object>(); |
108 } | 117 } |
109 | 118 |
110 // Placeholder for return value. | 119 // Placeholder for return value. |
111 Object* value = NULL; | 120 Object* value = NULL; |
112 | 121 |
113 typedef Object* (*JSEntryFunction)(Object* new_target, Object* target, | 122 typedef Object* (*JSEntryFunction)(Object* new_target, Object* target, |
114 Object* receiver, int argc, | 123 Object* receiver, int argc, |
115 Object*** args); | 124 Object*** args); |
116 | 125 |
(...skipping 26 matching lines...) Expand all Loading... |
143 #ifdef VERIFY_HEAP | 152 #ifdef VERIFY_HEAP |
144 if (FLAG_verify_heap) { | 153 if (FLAG_verify_heap) { |
145 value->ObjectVerify(); | 154 value->ObjectVerify(); |
146 } | 155 } |
147 #endif | 156 #endif |
148 | 157 |
149 // Update the pending exception flag and return the value. | 158 // Update the pending exception flag and return the value. |
150 bool has_exception = value->IsException(isolate); | 159 bool has_exception = value->IsException(isolate); |
151 DCHECK(has_exception == isolate->has_pending_exception()); | 160 DCHECK(has_exception == isolate->has_pending_exception()); |
152 if (has_exception) { | 161 if (has_exception) { |
153 isolate->ReportPendingMessages(); | 162 if (message_handling == MessageHandling::kReport) { |
| 163 isolate->ReportPendingMessages(); |
| 164 } |
154 return MaybeHandle<Object>(); | 165 return MaybeHandle<Object>(); |
155 } else { | 166 } else { |
156 isolate->clear_pending_message(); | 167 isolate->clear_pending_message(); |
157 } | 168 } |
158 | 169 |
159 return Handle<Object>(value, isolate); | 170 return Handle<Object>(value, isolate); |
160 } | 171 } |
161 | 172 |
162 } // namespace | 173 MaybeHandle<Object> CallInternal(Isolate* isolate, Handle<Object> callable, |
163 | 174 Handle<Object> receiver, int argc, |
164 | 175 Handle<Object> argv[], |
165 // static | 176 MessageHandling message_handling) { |
166 MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable, | |
167 Handle<Object> receiver, int argc, | |
168 Handle<Object> argv[]) { | |
169 // Convert calls on global objects to be calls on the global | 177 // Convert calls on global objects to be calls on the global |
170 // receiver instead to avoid having a 'this' pointer which refers | 178 // receiver instead to avoid having a 'this' pointer which refers |
171 // directly to a global object. | 179 // directly to a global object. |
172 if (receiver->IsJSGlobalObject()) { | 180 if (receiver->IsJSGlobalObject()) { |
173 receiver = | 181 receiver = |
174 handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(), isolate); | 182 handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(), isolate); |
175 } | 183 } |
176 return Invoke(isolate, false, callable, receiver, argc, argv, | 184 return Invoke(isolate, false, callable, receiver, argc, argv, |
177 isolate->factory()->undefined_value()); | 185 isolate->factory()->undefined_value(), message_handling); |
| 186 } |
| 187 |
| 188 } // namespace |
| 189 |
| 190 // static |
| 191 MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable, |
| 192 Handle<Object> receiver, int argc, |
| 193 Handle<Object> argv[]) { |
| 194 return CallInternal(isolate, callable, receiver, argc, argv, |
| 195 MessageHandling::kReport); |
178 } | 196 } |
179 | 197 |
180 | 198 |
181 // static | 199 // static |
182 MaybeHandle<Object> Execution::New(Handle<JSFunction> constructor, int argc, | 200 MaybeHandle<Object> Execution::New(Handle<JSFunction> constructor, int argc, |
183 Handle<Object> argv[]) { | 201 Handle<Object> argv[]) { |
184 return New(constructor->GetIsolate(), constructor, constructor, argc, argv); | 202 return New(constructor->GetIsolate(), constructor, constructor, argc, argv); |
185 } | 203 } |
186 | 204 |
187 | 205 |
188 // static | 206 // static |
189 MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor, | 207 MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor, |
190 Handle<Object> new_target, int argc, | 208 Handle<Object> new_target, int argc, |
191 Handle<Object> argv[]) { | 209 Handle<Object> argv[]) { |
192 return Invoke(isolate, true, constructor, | 210 return Invoke(isolate, true, constructor, |
193 isolate->factory()->undefined_value(), argc, argv, new_target); | 211 isolate->factory()->undefined_value(), argc, argv, new_target, |
| 212 MessageHandling::kReport); |
194 } | 213 } |
195 | 214 |
196 | 215 |
197 MaybeHandle<Object> Execution::TryCall(Isolate* isolate, | 216 MaybeHandle<Object> Execution::TryCall(Isolate* isolate, |
198 Handle<Object> callable, | 217 Handle<Object> callable, |
199 Handle<Object> receiver, int argc, | 218 Handle<Object> receiver, int argc, |
200 Handle<Object> args[], | 219 Handle<Object> args[], |
201 MaybeHandle<Object>* exception_out) { | 220 MaybeHandle<Object>* exception_out) { |
202 bool is_termination = false; | 221 bool is_termination = false; |
203 MaybeHandle<Object> maybe_result; | 222 MaybeHandle<Object> maybe_result; |
204 if (exception_out != NULL) *exception_out = MaybeHandle<Object>(); | 223 if (exception_out != NULL) *exception_out = MaybeHandle<Object>(); |
205 // Enter a try-block while executing the JavaScript code. To avoid | 224 // Enter a try-block while executing the JavaScript code. To avoid |
206 // duplicate error printing it must be non-verbose. Also, to avoid | 225 // duplicate error printing it must be non-verbose. Also, to avoid |
207 // creating message objects during stack overflow we shouldn't | 226 // creating message objects during stack overflow we shouldn't |
208 // capture messages. | 227 // capture messages. |
209 { | 228 { |
210 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate)); | 229 v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate)); |
211 catcher.SetVerbose(false); | 230 catcher.SetVerbose(false); |
212 catcher.SetCaptureMessage(false); | 231 catcher.SetCaptureMessage(false); |
213 | 232 |
214 maybe_result = Call(isolate, callable, receiver, argc, args); | 233 maybe_result = |
| 234 CallInternal(isolate, callable, receiver, argc, args, |
| 235 exception_out != nullptr ? MessageHandling::kReport |
| 236 : MessageHandling::kKeep); |
215 | 237 |
216 if (maybe_result.is_null()) { | 238 if (maybe_result.is_null()) { |
217 DCHECK(catcher.HasCaught()); | |
218 DCHECK(isolate->has_pending_exception()); | 239 DCHECK(isolate->has_pending_exception()); |
219 DCHECK(isolate->external_caught_exception()); | |
220 if (isolate->pending_exception() == | 240 if (isolate->pending_exception() == |
221 isolate->heap()->termination_exception()) { | 241 isolate->heap()->termination_exception()) { |
222 is_termination = true; | 242 is_termination = true; |
223 } else { | 243 } else { |
224 if (exception_out != NULL) { | 244 if (exception_out != nullptr) { |
| 245 DCHECK(catcher.HasCaught()); |
| 246 DCHECK(isolate->external_caught_exception()); |
225 *exception_out = v8::Utils::OpenHandle(*catcher.Exception()); | 247 *exception_out = v8::Utils::OpenHandle(*catcher.Exception()); |
226 } | 248 } |
227 } | 249 } |
228 isolate->OptionalRescheduleException(true); | 250 if (exception_out != nullptr) { |
| 251 isolate->OptionalRescheduleException(true); |
| 252 } |
229 } | 253 } |
230 | |
231 DCHECK(!isolate->has_pending_exception()); | |
232 } | 254 } |
233 | 255 |
234 // Re-request terminate execution interrupt to trigger later. | 256 // Re-request terminate execution interrupt to trigger later. |
235 if (is_termination) isolate->stack_guard()->RequestTerminateExecution(); | 257 if (is_termination) isolate->stack_guard()->RequestTerminateExecution(); |
236 | 258 |
237 return maybe_result; | 259 return maybe_result; |
238 } | 260 } |
239 | 261 |
240 | 262 |
241 void StackGuard::SetStackLimit(uintptr_t limit) { | 263 void StackGuard::SetStackLimit(uintptr_t limit) { |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 | 497 |
476 isolate_->counters()->stack_interrupts()->Increment(); | 498 isolate_->counters()->stack_interrupts()->Increment(); |
477 isolate_->counters()->runtime_profiler_ticks()->Increment(); | 499 isolate_->counters()->runtime_profiler_ticks()->Increment(); |
478 isolate_->runtime_profiler()->MarkCandidatesForOptimization(); | 500 isolate_->runtime_profiler()->MarkCandidatesForOptimization(); |
479 | 501 |
480 return isolate_->heap()->undefined_value(); | 502 return isolate_->heap()->undefined_value(); |
481 } | 503 } |
482 | 504 |
483 } // namespace internal | 505 } // namespace internal |
484 } // namespace v8 | 506 } // namespace v8 |
OLD | NEW |