File: | out/../deps/v8/src/execution/execution.cc |
Warning: | line 64, column 45 Forming reference to null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |||
3 | // found in the LICENSE file. | |||
4 | ||||
5 | #include "src/execution/execution.h" | |||
6 | ||||
7 | #include "src/api/api-inl.h" | |||
8 | #include "src/debug/debug.h" | |||
9 | #include "src/execution/frames.h" | |||
10 | #include "src/execution/isolate-inl.h" | |||
11 | #include "src/execution/vm-state-inl.h" | |||
12 | #include "src/logging/runtime-call-stats-scope.h" | |||
13 | ||||
14 | #if V8_ENABLE_WEBASSEMBLY1 | |||
15 | #include "src/compiler/wasm-compiler.h" // Only for static asserts. | |||
16 | #include "src/wasm/code-space-access.h" | |||
17 | #include "src/wasm/wasm-engine.h" | |||
18 | #endif // V8_ENABLE_WEBASSEMBLY | |||
19 | ||||
20 | namespace v8 { | |||
21 | namespace internal { | |||
22 | ||||
23 | namespace { | |||
24 | ||||
25 | Handle<Object> NormalizeReceiver(Isolate* isolate, Handle<Object> receiver) { | |||
26 | // Convert calls on global objects to be calls on the global | |||
27 | // receiver instead to avoid having a 'this' pointer which refers | |||
28 | // directly to a global object. | |||
29 | if (receiver->IsJSGlobalObject()) { | |||
30 | return handle(Handle<JSGlobalObject>::cast(receiver)->global_proxy(), | |||
31 | isolate); | |||
32 | } | |||
33 | return receiver; | |||
34 | } | |||
35 | ||||
36 | struct InvokeParams { | |||
37 | static InvokeParams SetUpForNew(Isolate* isolate, Handle<Object> constructor, | |||
38 | Handle<Object> new_target, int argc, | |||
39 | Handle<Object>* argv); | |||
40 | ||||
41 | static InvokeParams SetUpForCall(Isolate* isolate, Handle<Object> callable, | |||
42 | Handle<Object> receiver, int argc, | |||
43 | Handle<Object>* argv); | |||
44 | ||||
45 | static InvokeParams SetUpForTryCall( | |||
46 | Isolate* isolate, Handle<Object> callable, Handle<Object> receiver, | |||
47 | int argc, Handle<Object>* argv, | |||
48 | Execution::MessageHandling message_handling, | |||
49 | MaybeHandle<Object>* exception_out, bool reschedule_terminate); | |||
50 | ||||
51 | static InvokeParams SetUpForRunMicrotasks(Isolate* isolate, | |||
52 | MicrotaskQueue* microtask_queue, | |||
53 | MaybeHandle<Object>* exception_out); | |||
54 | ||||
55 | bool IsScript() const { | |||
56 | if (!target->IsJSFunction()) return false; | |||
57 | Handle<JSFunction> function = Handle<JSFunction>::cast(target); | |||
58 | return function->shared().is_script(); | |||
59 | } | |||
60 | ||||
61 | Handle<FixedArray> GetAndResetHostDefinedOptions() { | |||
62 | DCHECK(IsScript())((void) 0); | |||
63 | DCHECK_EQ(argc, 1)((void) 0); | |||
64 | auto options = Handle<FixedArray>::cast(argv[0]); | |||
| ||||
65 | argv = nullptr; | |||
66 | argc = 0; | |||
67 | return options; | |||
68 | } | |||
69 | ||||
70 | Handle<Object> target; | |||
71 | Handle<Object> receiver; | |||
72 | int argc; | |||
73 | Handle<Object>* argv; | |||
74 | Handle<Object> new_target; | |||
75 | ||||
76 | MicrotaskQueue* microtask_queue; | |||
77 | ||||
78 | Execution::MessageHandling message_handling; | |||
79 | MaybeHandle<Object>* exception_out; | |||
80 | ||||
81 | bool is_construct; | |||
82 | Execution::Target execution_target; | |||
83 | bool reschedule_terminate; | |||
84 | }; | |||
85 | ||||
86 | // static | |||
87 | InvokeParams InvokeParams::SetUpForNew(Isolate* isolate, | |||
88 | Handle<Object> constructor, | |||
89 | Handle<Object> new_target, int argc, | |||
90 | Handle<Object>* argv) { | |||
91 | InvokeParams params; | |||
92 | params.target = constructor; | |||
93 | params.receiver = isolate->factory()->undefined_value(); | |||
94 | DCHECK(!params.IsScript())((void) 0); | |||
95 | params.argc = argc; | |||
96 | params.argv = argv; | |||
97 | params.new_target = new_target; | |||
98 | params.microtask_queue = nullptr; | |||
99 | params.message_handling = Execution::MessageHandling::kReport; | |||
100 | params.exception_out = nullptr; | |||
101 | params.is_construct = true; | |||
102 | params.execution_target = Execution::Target::kCallable; | |||
103 | params.reschedule_terminate = true; | |||
104 | return params; | |||
105 | } | |||
106 | ||||
107 | // static | |||
108 | InvokeParams InvokeParams::SetUpForCall(Isolate* isolate, | |||
109 | Handle<Object> callable, | |||
110 | Handle<Object> receiver, int argc, | |||
111 | Handle<Object>* argv) { | |||
112 | InvokeParams params; | |||
113 | params.target = callable; | |||
114 | params.receiver = NormalizeReceiver(isolate, receiver); | |||
115 | // Check for host-defined options argument for scripts. | |||
116 | DCHECK_IMPLIES(params.IsScript(), argc == 1)((void) 0); | |||
117 | DCHECK_IMPLIES(params.IsScript(), argv[0]->IsFixedArray())((void) 0); | |||
118 | params.argc = argc; | |||
119 | params.argv = argv; | |||
120 | params.new_target = isolate->factory()->undefined_value(); | |||
121 | params.microtask_queue = nullptr; | |||
122 | params.message_handling = Execution::MessageHandling::kReport; | |||
123 | params.exception_out = nullptr; | |||
124 | params.is_construct = false; | |||
125 | params.execution_target = Execution::Target::kCallable; | |||
126 | params.reschedule_terminate = true; | |||
127 | return params; | |||
128 | } | |||
129 | ||||
130 | // static | |||
131 | InvokeParams InvokeParams::SetUpForTryCall( | |||
132 | Isolate* isolate, Handle<Object> callable, Handle<Object> receiver, | |||
133 | int argc, Handle<Object>* argv, Execution::MessageHandling message_handling, | |||
134 | MaybeHandle<Object>* exception_out, bool reschedule_terminate) { | |||
135 | InvokeParams params; | |||
136 | params.target = callable; | |||
137 | params.receiver = NormalizeReceiver(isolate, receiver); | |||
138 | // Check for host-defined options argument for scripts. | |||
139 | DCHECK_IMPLIES(params.IsScript(), argc == 1)((void) 0); | |||
140 | DCHECK_IMPLIES(params.IsScript(), argv[0]->IsFixedArray())((void) 0); | |||
141 | params.argc = argc; | |||
142 | params.argv = argv; | |||
143 | params.new_target = isolate->factory()->undefined_value(); | |||
144 | params.microtask_queue = nullptr; | |||
145 | params.message_handling = message_handling; | |||
146 | params.exception_out = exception_out; | |||
147 | params.is_construct = false; | |||
148 | params.execution_target = Execution::Target::kCallable; | |||
149 | params.reschedule_terminate = reschedule_terminate; | |||
150 | return params; | |||
151 | } | |||
152 | ||||
153 | // static | |||
154 | InvokeParams InvokeParams::SetUpForRunMicrotasks( | |||
155 | Isolate* isolate, MicrotaskQueue* microtask_queue, | |||
156 | MaybeHandle<Object>* exception_out) { | |||
157 | auto undefined = isolate->factory()->undefined_value(); | |||
158 | InvokeParams params; | |||
159 | params.target = undefined; | |||
160 | params.receiver = undefined; | |||
161 | params.argc = 0; | |||
162 | params.argv = nullptr; | |||
163 | params.new_target = undefined; | |||
164 | params.microtask_queue = microtask_queue; | |||
165 | params.message_handling = Execution::MessageHandling::kReport; | |||
166 | params.exception_out = exception_out; | |||
167 | params.is_construct = false; | |||
168 | params.execution_target = Execution::Target::kRunMicrotasks; | |||
169 | params.reschedule_terminate = true; | |||
170 | return params; | |||
171 | } | |||
172 | ||||
173 | Handle<CodeT> JSEntry(Isolate* isolate, Execution::Target execution_target, | |||
174 | bool is_construct) { | |||
175 | if (is_construct) { | |||
176 | DCHECK_EQ(Execution::Target::kCallable, execution_target)((void) 0); | |||
177 | return BUILTIN_CODE(isolate, JSConstructEntry)(isolate)->builtins()->code_handle(i::Builtin::kJSConstructEntry ); | |||
178 | } else if (execution_target == Execution::Target::kCallable) { | |||
179 | DCHECK(!is_construct)((void) 0); | |||
180 | return BUILTIN_CODE(isolate, JSEntry)(isolate)->builtins()->code_handle(i::Builtin::kJSEntry ); | |||
181 | } else if (execution_target == Execution::Target::kRunMicrotasks) { | |||
182 | DCHECK(!is_construct)((void) 0); | |||
183 | return BUILTIN_CODE(isolate, JSRunMicrotasksEntry)(isolate)->builtins()->code_handle(i::Builtin::kJSRunMicrotasksEntry ); | |||
184 | } | |||
185 | UNREACHABLE()V8_Fatal("unreachable code"); | |||
186 | } | |||
187 | ||||
188 | MaybeHandle<Context> NewScriptContext(Isolate* isolate, | |||
189 | Handle<JSFunction> function, | |||
190 | Handle<FixedArray> host_defined_options) { | |||
191 | // TODO(cbruni, 1244145): Use passed in host_defined_options. | |||
192 | // Creating a script context is a side effect, so abort if that's not | |||
193 | // allowed. | |||
194 | if (isolate->debug_execution_mode() == DebugInfo::kSideEffects) { | |||
195 | isolate->Throw(*isolate->factory()->NewEvalError( | |||
196 | MessageTemplate::kNoSideEffectDebugEvaluate)); | |||
197 | return MaybeHandle<Context>(); | |||
198 | } | |||
199 | SaveAndSwitchContext save(isolate, function->context()); | |||
200 | SharedFunctionInfo sfi = function->shared(); | |||
201 | Handle<Script> script(Script::cast(sfi.script()), isolate); | |||
202 | Handle<ScopeInfo> scope_info(sfi.scope_info(), isolate); | |||
203 | Handle<NativeContext> native_context(NativeContext::cast(function->context()), | |||
204 | isolate); | |||
205 | Handle<JSGlobalObject> global_object(native_context->global_object(), | |||
206 | isolate); | |||
207 | Handle<ScriptContextTable> script_context( | |||
208 | native_context->script_context_table(), isolate); | |||
209 | ||||
210 | // Find name clashes. | |||
211 | for (auto it : ScopeInfo::IterateLocalNames(scope_info)) { | |||
212 | Handle<String> name(it->name(), isolate); | |||
213 | VariableMode mode = scope_info->ContextLocalMode(it->index()); | |||
214 | VariableLookupResult lookup; | |||
215 | if (script_context->Lookup(name, &lookup)) { | |||
216 | if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) { | |||
217 | Handle<Context> context = ScriptContextTable::GetContext( | |||
218 | isolate, script_context, lookup.context_index); | |||
219 | // If we are trying to re-declare a REPL-mode let as a let or REPL-mode | |||
220 | // const as a const, allow it. | |||
221 | if (!(((mode == VariableMode::kLet && | |||
222 | lookup.mode == VariableMode::kLet) || | |||
223 | (mode == VariableMode::kConst && | |||
224 | lookup.mode == VariableMode::kConst)) && | |||
225 | scope_info->IsReplModeScope() && | |||
226 | context->scope_info().IsReplModeScope())) { | |||
227 | // ES#sec-globaldeclarationinstantiation 5.b: | |||
228 | // If envRec.HasLexicalDeclaration(name) is true, throw a SyntaxError | |||
229 | // exception. | |||
230 | MessageLocation location(script, 0, 1); | |||
231 | return isolate->ThrowAt<Context>( | |||
232 | isolate->factory()->NewSyntaxError( | |||
233 | MessageTemplate::kVarRedeclaration, name), | |||
234 | &location); | |||
235 | } | |||
236 | } | |||
237 | } | |||
238 | ||||
239 | if (IsLexicalVariableMode(mode)) { | |||
240 | LookupIterator it(isolate, global_object, name, global_object, | |||
241 | LookupIterator::OWN_SKIP_INTERCEPTOR); | |||
242 | Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it); | |||
243 | // Can't fail since the we looking up own properties on the global object | |||
244 | // skipping interceptors. | |||
245 | CHECK(!maybe.IsNothing())do { if ((__builtin_expect(!!(!(!maybe.IsNothing())), 0))) { V8_Fatal ("Check failed: %s.", "!maybe.IsNothing()"); } } while (false ); | |||
246 | if ((maybe.FromJust() & DONT_DELETE) != 0) { | |||
247 | // ES#sec-globaldeclarationinstantiation 5.a: | |||
248 | // If envRec.HasVarDeclaration(name) is true, throw a SyntaxError | |||
249 | // exception. | |||
250 | // ES#sec-globaldeclarationinstantiation 5.d: | |||
251 | // If hasRestrictedGlobal is true, throw a SyntaxError exception. | |||
252 | MessageLocation location(script, 0, 1); | |||
253 | return isolate->ThrowAt<Context>( | |||
254 | isolate->factory()->NewSyntaxError( | |||
255 | MessageTemplate::kVarRedeclaration, name), | |||
256 | &location); | |||
257 | } | |||
258 | ||||
259 | JSGlobalObject::InvalidatePropertyCell(global_object, name); | |||
260 | } | |||
261 | } | |||
262 | ||||
263 | Handle<Context> result = | |||
264 | isolate->factory()->NewScriptContext(native_context, scope_info); | |||
265 | ||||
266 | result->Initialize(isolate); | |||
267 | // In REPL mode, we are allowed to add/modify let/const variables. | |||
268 | // We use the previous defined script context for those. | |||
269 | const bool ignore_duplicates = scope_info->IsReplModeScope(); | |||
270 | Handle<ScriptContextTable> new_script_context_table = | |||
271 | ScriptContextTable::Extend(isolate, script_context, result, | |||
272 | ignore_duplicates); | |||
273 | native_context->synchronized_set_script_context_table( | |||
274 | *new_script_context_table); | |||
275 | return result; | |||
276 | } | |||
277 | ||||
278 | V8_WARN_UNUSED_RESULT__attribute__((warn_unused_result)) MaybeHandle<Object> Invoke(Isolate* isolate, | |||
279 | const InvokeParams& params) { | |||
280 | RCS_SCOPE(isolate, RuntimeCallCounterId::kInvoke); | |||
281 | DCHECK(!params.receiver->IsJSGlobalObject())((void) 0); | |||
282 | DCHECK_LE(params.argc, FixedArray::kMaxLength)((void) 0); | |||
283 | ||||
284 | #if V8_ENABLE_WEBASSEMBLY1 | |||
285 | // When executing JS code, there should be no {CodeSpaceWriteScope} open. | |||
286 | DCHECK(!wasm::CodeSpaceWriteScope::IsInScope())((void) 0); | |||
287 | // If we have PKU support for Wasm, ensure that code is currently write | |||
288 | // protected for this thread. | |||
289 | DCHECK_IMPLIES(wasm::GetWasmCodeManager()->HasMemoryProtectionKeySupport(),((void) 0) | |||
290 | !wasm::GetWasmCodeManager()->MemoryProtectionKeyWritable())((void) 0); | |||
291 | #endif // V8_ENABLE_WEBASSEMBLY | |||
292 | ||||
293 | #ifdef USE_SIMULATOR | |||
294 | // Simulators use separate stacks for C++ and JS. JS stack overflow checks | |||
295 | // are performed whenever a JS function is called. However, it can be the case | |||
296 | // that the C++ stack grows faster than the JS stack, resulting in an overflow | |||
297 | // there. Add a check here to make that less likely. | |||
298 | StackLimitCheck check(isolate); | |||
299 | if (check.HasOverflowed()) { | |||
300 | isolate->StackOverflow(); | |||
301 | if (params.message_handling == Execution::MessageHandling::kReport) { | |||
302 | isolate->ReportPendingMessages(); | |||
303 | } | |||
304 | return MaybeHandle<Object>(); | |||
305 | } | |||
306 | #endif | |||
307 | ||||
308 | // api callbacks can be called directly, unless we want to take the detour | |||
309 | // through JS to set up a frame for break-at-entry. | |||
310 | if (params.target->IsJSFunction()) { | |||
311 | Handle<JSFunction> function = Handle<JSFunction>::cast(params.target); | |||
312 | if ((!params.is_construct
| |||
313 | function->shared().IsApiFunction() && | |||
314 | !function->shared().BreakAtEntry()) { | |||
315 | SaveAndSwitchContext save(isolate, function->context()); | |||
316 | DCHECK(function->context().global_object().IsJSGlobalObject())((void) 0); | |||
317 | ||||
318 | Handle<Object> receiver = params.is_construct | |||
319 | ? isolate->factory()->the_hole_value() | |||
320 | : params.receiver; | |||
321 | auto value = Builtins::InvokeApiFunction( | |||
322 | isolate, params.is_construct, function, receiver, params.argc, | |||
323 | params.argv, Handle<HeapObject>::cast(params.new_target)); | |||
324 | bool has_exception = value.is_null(); | |||
325 | DCHECK(has_exception == isolate->has_pending_exception())((void) 0); | |||
326 | if (has_exception) { | |||
327 | if (params.message_handling == Execution::MessageHandling::kReport) { | |||
328 | isolate->ReportPendingMessages(); | |||
329 | } | |||
330 | return MaybeHandle<Object>(); | |||
331 | } else { | |||
332 | isolate->clear_pending_message(); | |||
333 | } | |||
334 | return value; | |||
335 | } | |||
336 | #ifdef DEBUG | |||
337 | if (function->shared().is_script()) { | |||
338 | DCHECK(params.IsScript())((void) 0); | |||
339 | DCHECK(params.receiver->IsJSGlobalProxy())((void) 0); | |||
340 | DCHECK_EQ(params.argc, 1)((void) 0); | |||
341 | DCHECK(params.argv[0]->IsFixedArray())((void) 0); | |||
342 | } else { | |||
343 | DCHECK(!params.IsScript())((void) 0); | |||
344 | } | |||
345 | #endif | |||
346 | // Set up a ScriptContext when running scripts that need it. | |||
347 | if (function->shared().needs_script_context()) { | |||
348 | Handle<Context> context; | |||
349 | Handle<FixedArray> host_defined_options = | |||
350 | const_cast<InvokeParams&>(params).GetAndResetHostDefinedOptions(); | |||
351 | if (!NewScriptContext(isolate, function, host_defined_options) | |||
352 | .ToHandle(&context)) { | |||
353 | if (params.message_handling == Execution::MessageHandling::kReport) { | |||
354 | isolate->ReportPendingMessages(); | |||
355 | } | |||
356 | return MaybeHandle<Object>(); | |||
357 | } | |||
358 | ||||
359 | // We mutate the context if we allocate a script context. This is | |||
360 | // guaranteed to only happen once in a native context since scripts will | |||
361 | // always produce name clashes with themselves. | |||
362 | function->set_context(*context); | |||
363 | } | |||
364 | } | |||
365 | ||||
366 | // Entering JavaScript. | |||
367 | VMState<JS> state(isolate); | |||
368 | CHECK(AllowJavascriptExecution::IsAllowed(isolate))do { if ((__builtin_expect(!!(!(AllowJavascriptExecution::IsAllowed (isolate))), 0))) { V8_Fatal("Check failed: %s.", "AllowJavascriptExecution::IsAllowed(isolate)" ); } } while (false); | |||
369 | if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { | |||
370 | isolate->ThrowIllegalOperation(); | |||
371 | if (params.message_handling == Execution::MessageHandling::kReport) { | |||
372 | isolate->ReportPendingMessages(); | |||
373 | } | |||
374 | return MaybeHandle<Object>(); | |||
375 | } | |||
376 | if (!DumpOnJavascriptExecution::IsAllowed(isolate)) { | |||
377 | V8::GetCurrentPlatform()->DumpWithoutCrashing(); | |||
378 | return isolate->factory()->undefined_value(); | |||
379 | } | |||
380 | ||||
381 | if (params.execution_target == Execution::Target::kCallable) { | |||
382 | Handle<Context> context = isolate->native_context(); | |||
383 | if (!context->script_execution_callback().IsUndefined(isolate)) { | |||
384 | v8::Context::AbortScriptExecutionCallback callback = | |||
385 | v8::ToCData<v8::Context::AbortScriptExecutionCallback>( | |||
386 | context->script_execution_callback()); | |||
387 | v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate); | |||
388 | v8::Local<v8::Context> api_context = v8::Utils::ToLocal(context); | |||
389 | callback(api_isolate, api_context); | |||
390 | DCHECK(!isolate->has_scheduled_exception())((void) 0); | |||
391 | // Always throw an exception to abort execution, if callback exists. | |||
392 | isolate->ThrowIllegalOperation(); | |||
393 | return MaybeHandle<Object>(); | |||
394 | } | |||
395 | } | |||
396 | ||||
397 | // Placeholder for return value. | |||
398 | Object value; | |||
399 | Handle<CodeT> code = | |||
400 | JSEntry(isolate, params.execution_target, params.is_construct); | |||
401 | { | |||
402 | // Save and restore context around invocation and block the | |||
403 | // allocation of handles without explicit handle scopes. | |||
404 | SaveContext save(isolate); | |||
405 | SealHandleScope shs(isolate); | |||
406 | ||||
407 | if (FLAG_clear_exceptions_on_js_entry) isolate->clear_pending_exception(); | |||
408 | ||||
409 | if (params.execution_target == Execution::Target::kCallable) { | |||
410 | // clang-format off | |||
411 | // {new_target}, {target}, {receiver}, return value: tagged pointers | |||
412 | // {argv}: pointer to array of tagged pointers | |||
413 | using JSEntryFunction = GeneratedCode<Address( | |||
414 | Address root_register_value, Address new_target, Address target, | |||
415 | Address receiver, intptr_t argc, Address** argv)>; | |||
416 | // clang-format on | |||
417 | JSEntryFunction stub_entry = | |||
418 | JSEntryFunction::FromAddress(isolate, code->InstructionStart()); | |||
419 | ||||
420 | Address orig_func = params.new_target->ptr(); | |||
421 | Address func = params.target->ptr(); | |||
422 | Address recv = params.receiver->ptr(); | |||
423 | Address** argv = reinterpret_cast<Address**>(params.argv); | |||
424 | RCS_SCOPE(isolate, RuntimeCallCounterId::kJS_Execution); | |||
425 | value = Object(stub_entry.Call(isolate->isolate_data()->isolate_root(), | |||
426 | orig_func, func, recv, | |||
427 | JSParameterCount(params.argc), argv)); | |||
428 | } else { | |||
429 | DCHECK_EQ(Execution::Target::kRunMicrotasks, params.execution_target)((void) 0); | |||
430 | ||||
431 | // clang-format off | |||
432 | // return value: tagged pointers | |||
433 | // {microtask_queue}: pointer to a C++ object | |||
434 | using JSEntryFunction = GeneratedCode<Address( | |||
435 | Address root_register_value, MicrotaskQueue* microtask_queue)>; | |||
436 | // clang-format on | |||
437 | JSEntryFunction stub_entry = | |||
438 | JSEntryFunction::FromAddress(isolate, code->InstructionStart()); | |||
439 | ||||
440 | RCS_SCOPE(isolate, RuntimeCallCounterId::kJS_Execution); | |||
441 | value = Object(stub_entry.Call(isolate->isolate_data()->isolate_root(), | |||
442 | params.microtask_queue)); | |||
443 | } | |||
444 | } | |||
445 | ||||
446 | #ifdef VERIFY_HEAP | |||
447 | if (FLAG_verify_heap) { | |||
448 | value.ObjectVerify(isolate); | |||
449 | } | |||
450 | #endif | |||
451 | ||||
452 | // Update the pending exception flag and return the value. | |||
453 | bool has_exception = value.IsException(isolate); | |||
454 | DCHECK(has_exception == isolate->has_pending_exception())((void) 0); | |||
455 | if (has_exception) { | |||
456 | if (params.message_handling == Execution::MessageHandling::kReport) { | |||
457 | isolate->ReportPendingMessages(); | |||
458 | } | |||
459 | return MaybeHandle<Object>(); | |||
460 | } else { | |||
461 | isolate->clear_pending_message(); | |||
462 | } | |||
463 | ||||
464 | return Handle<Object>(value, isolate); | |||
465 | } | |||
466 | ||||
467 | MaybeHandle<Object> InvokeWithTryCatch(Isolate* isolate, | |||
468 | const InvokeParams& params) { | |||
469 | bool is_termination = false; | |||
470 | MaybeHandle<Object> maybe_result; | |||
471 | if (params.exception_out != nullptr) { | |||
472 | *params.exception_out = MaybeHandle<Object>(); | |||
473 | } | |||
474 | DCHECK_IMPLIES(((void) 0) | |||
475 | params.message_handling == Execution::MessageHandling::kKeepPending,((void) 0) | |||
476 | params.exception_out == nullptr)((void) 0); | |||
477 | // Enter a try-block while executing the JavaScript code. To avoid | |||
478 | // duplicate error printing it must be non-verbose. Also, to avoid | |||
479 | // creating message objects during stack overflow we shouldn't | |||
480 | // capture messages. | |||
481 | { | |||
482 | v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate)); | |||
483 | catcher.SetVerbose(false); | |||
484 | catcher.SetCaptureMessage(false); | |||
485 | ||||
486 | maybe_result = Invoke(isolate, params); | |||
487 | ||||
488 | if (maybe_result.is_null()) { | |||
489 | DCHECK(isolate->has_pending_exception())((void) 0); | |||
490 | if (isolate->pending_exception() == | |||
491 | ReadOnlyRoots(isolate).termination_exception()) { | |||
492 | is_termination = true; | |||
493 | } else { | |||
494 | if (params.exception_out != nullptr) { | |||
495 | DCHECK(catcher.HasCaught())((void) 0); | |||
496 | DCHECK(isolate->external_caught_exception())((void) 0); | |||
497 | *params.exception_out = v8::Utils::OpenHandle(*catcher.Exception()); | |||
498 | } | |||
499 | if (params.message_handling == Execution::MessageHandling::kReport) { | |||
500 | isolate->OptionalRescheduleException(true); | |||
501 | } | |||
502 | } | |||
503 | } | |||
504 | } | |||
505 | ||||
506 | if (is_termination && params.reschedule_terminate) { | |||
507 | // Reschedule terminate execution exception. | |||
508 | isolate->OptionalRescheduleException(false); | |||
509 | } | |||
510 | ||||
511 | return maybe_result; | |||
512 | } | |||
513 | ||||
514 | } // namespace | |||
515 | ||||
516 | // static | |||
517 | MaybeHandle<Object> Execution::Call(Isolate* isolate, Handle<Object> callable, | |||
518 | Handle<Object> receiver, int argc, | |||
519 | Handle<Object> argv[]) { | |||
520 | // Use Execution::CallScript instead for scripts: | |||
521 | DCHECK_IMPLIES(callable->IsJSFunction(),((void) 0) | |||
522 | !JSFunction::cast(*callable).shared().is_script())((void) 0); | |||
523 | return Invoke(isolate, InvokeParams::SetUpForCall(isolate, callable, receiver, | |||
524 | argc, argv)); | |||
525 | } | |||
526 | ||||
527 | // static | |||
528 | MaybeHandle<Object> Execution::CallScript(Isolate* isolate, | |||
529 | Handle<JSFunction> script_function, | |||
530 | Handle<Object> receiver, | |||
531 | Handle<Object> host_defined_options) { | |||
532 | DCHECK(script_function->shared().is_script())((void) 0); | |||
533 | DCHECK(receiver->IsJSGlobalProxy() || receiver->IsJSGlobalObject())((void) 0); | |||
534 | return Invoke( | |||
535 | isolate, InvokeParams::SetUpForCall(isolate, script_function, receiver, 1, | |||
536 | &host_defined_options)); | |||
537 | } | |||
538 | ||||
539 | MaybeHandle<Object> Execution::CallBuiltin(Isolate* isolate, | |||
540 | Handle<JSFunction> builtin, | |||
541 | Handle<Object> receiver, int argc, | |||
542 | Handle<Object> argv[]) { | |||
543 | DCHECK(builtin->code().is_builtin())((void) 0); | |||
544 | DisableBreak no_break(isolate->debug()); | |||
545 | return Invoke(isolate, InvokeParams::SetUpForCall(isolate, builtin, receiver, | |||
546 | argc, argv)); | |||
547 | } | |||
548 | ||||
549 | // static | |||
550 | MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor, | |||
551 | int argc, Handle<Object> argv[]) { | |||
552 | return New(isolate, constructor, constructor, argc, argv); | |||
553 | } | |||
554 | ||||
555 | // static | |||
556 | MaybeHandle<Object> Execution::New(Isolate* isolate, Handle<Object> constructor, | |||
557 | Handle<Object> new_target, int argc, | |||
558 | Handle<Object> argv[]) { | |||
559 | return Invoke(isolate, InvokeParams::SetUpForNew(isolate, constructor, | |||
560 | new_target, argc, argv)); | |||
561 | } | |||
562 | ||||
563 | // static | |||
564 | MaybeHandle<Object> Execution::TryCallScript( | |||
565 | Isolate* isolate, Handle<JSFunction> script_function, | |||
566 | Handle<Object> receiver, Handle<FixedArray> host_defined_options, | |||
567 | MessageHandling message_handling, MaybeHandle<Object>* exception_out, | |||
568 | bool reschedule_terminate) { | |||
569 | DCHECK(script_function->shared().is_script())((void) 0); | |||
570 | DCHECK(receiver->IsJSGlobalProxy() || receiver->IsJSGlobalObject())((void) 0); | |||
571 | Handle<Object> argument = host_defined_options; | |||
572 | return InvokeWithTryCatch( | |||
573 | isolate, InvokeParams::SetUpForTryCall( | |||
574 | isolate, script_function, receiver, 1, &argument, | |||
575 | message_handling, exception_out, reschedule_terminate)); | |||
576 | } | |||
577 | ||||
578 | // static | |||
579 | MaybeHandle<Object> Execution::TryCall( | |||
580 | Isolate* isolate, Handle<Object> callable, Handle<Object> receiver, | |||
581 | int argc, Handle<Object> argv[], MessageHandling message_handling, | |||
582 | MaybeHandle<Object>* exception_out, bool reschedule_terminate) { | |||
583 | // Use Execution::TryCallScript instead for scripts: | |||
584 | DCHECK_IMPLIES(callable->IsJSFunction(),((void) 0) | |||
585 | !JSFunction::cast(*callable).shared().is_script())((void) 0); | |||
586 | return InvokeWithTryCatch( | |||
587 | isolate, InvokeParams::SetUpForTryCall( | |||
588 | isolate, callable, receiver, argc, argv, message_handling, | |||
589 | exception_out, reschedule_terminate)); | |||
590 | } | |||
591 | ||||
592 | // static | |||
593 | MaybeHandle<Object> Execution::TryRunMicrotasks( | |||
594 | Isolate* isolate, MicrotaskQueue* microtask_queue, | |||
595 | MaybeHandle<Object>* exception_out) { | |||
596 | return InvokeWithTryCatch( | |||
597 | isolate, InvokeParams::SetUpForRunMicrotasks(isolate, microtask_queue, | |||
| ||||
598 | exception_out)); | |||
599 | } | |||
600 | ||||
601 | struct StackHandlerMarker { | |||
602 | Address next; | |||
603 | Address padding; | |||
604 | }; | |||
605 | STATIC_ASSERT(offsetof(StackHandlerMarker, next) ==static_assert(__builtin_offsetof(StackHandlerMarker, next) == StackHandlerConstants::kNextOffset, "offsetof(StackHandlerMarker, next) == StackHandlerConstants::kNextOffset" ) | |||
606 | StackHandlerConstants::kNextOffset)static_assert(__builtin_offsetof(StackHandlerMarker, next) == StackHandlerConstants::kNextOffset, "offsetof(StackHandlerMarker, next) == StackHandlerConstants::kNextOffset" ); | |||
607 | STATIC_ASSERT(offsetof(StackHandlerMarker, padding) ==static_assert(__builtin_offsetof(StackHandlerMarker, padding) == StackHandlerConstants::kPaddingOffset, "offsetof(StackHandlerMarker, padding) == StackHandlerConstants::kPaddingOffset" ) | |||
608 | StackHandlerConstants::kPaddingOffset)static_assert(__builtin_offsetof(StackHandlerMarker, padding) == StackHandlerConstants::kPaddingOffset, "offsetof(StackHandlerMarker, padding) == StackHandlerConstants::kPaddingOffset" ); | |||
609 | STATIC_ASSERT(sizeof(StackHandlerMarker) == StackHandlerConstants::kSize)static_assert(sizeof(StackHandlerMarker) == StackHandlerConstants ::kSize, "sizeof(StackHandlerMarker) == StackHandlerConstants::kSize" ); | |||
610 | ||||
611 | #if V8_ENABLE_WEBASSEMBLY1 | |||
612 | void Execution::CallWasm(Isolate* isolate, Handle<CodeT> wrapper_code, | |||
613 | Address wasm_call_target, Handle<Object> object_ref, | |||
614 | Address packed_args) { | |||
615 | using WasmEntryStub = GeneratedCode<Address( | |||
616 | Address target, Address object_ref, Address argv, Address c_entry_fp)>; | |||
617 | WasmEntryStub stub_entry = | |||
618 | WasmEntryStub::FromAddress(isolate, wrapper_code->InstructionStart()); | |||
619 | ||||
620 | // Save and restore context around invocation and block the | |||
621 | // allocation of handles without explicit handle scopes. | |||
622 | SaveContext save(isolate); | |||
623 | SealHandleScope shs(isolate); | |||
624 | ||||
625 | Address saved_c_entry_fp = *isolate->c_entry_fp_address(); | |||
626 | Address saved_js_entry_sp = *isolate->js_entry_sp_address(); | |||
627 | if (saved_js_entry_sp == kNullAddress) { | |||
628 | *isolate->js_entry_sp_address() = GetCurrentStackPosition(); | |||
629 | } | |||
630 | StackHandlerMarker stack_handler; | |||
631 | stack_handler.next = isolate->thread_local_top()->handler_; | |||
632 | #ifdef V8_USE_ADDRESS_SANITIZER | |||
633 | stack_handler.padding = GetCurrentStackPosition(); | |||
634 | #else | |||
635 | stack_handler.padding = 0; | |||
636 | #endif | |||
637 | isolate->thread_local_top()->handler_ = | |||
638 | reinterpret_cast<Address>(&stack_handler); | |||
639 | trap_handler::SetThreadInWasm(); | |||
640 | ||||
641 | { | |||
642 | RCS_SCOPE(isolate, RuntimeCallCounterId::kJS_Execution); | |||
643 | STATIC_ASSERT(compiler::CWasmEntryParameters::kCodeEntry == 0)static_assert(compiler::CWasmEntryParameters::kCodeEntry == 0 , "compiler::CWasmEntryParameters::kCodeEntry == 0"); | |||
644 | STATIC_ASSERT(compiler::CWasmEntryParameters::kObjectRef == 1)static_assert(compiler::CWasmEntryParameters::kObjectRef == 1 , "compiler::CWasmEntryParameters::kObjectRef == 1"); | |||
645 | STATIC_ASSERT(compiler::CWasmEntryParameters::kArgumentsBuffer == 2)static_assert(compiler::CWasmEntryParameters::kArgumentsBuffer == 2, "compiler::CWasmEntryParameters::kArgumentsBuffer == 2" ); | |||
646 | STATIC_ASSERT(compiler::CWasmEntryParameters::kCEntryFp == 3)static_assert(compiler::CWasmEntryParameters::kCEntryFp == 3, "compiler::CWasmEntryParameters::kCEntryFp == 3"); | |||
647 | Address result = stub_entry.Call(wasm_call_target, object_ref->ptr(), | |||
648 | packed_args, saved_c_entry_fp); | |||
649 | if (result != kNullAddress) { | |||
650 | isolate->set_pending_exception(Object(result)); | |||
651 | } | |||
652 | } | |||
653 | ||||
654 | // If there was an exception, then the thread-in-wasm flag is cleared | |||
655 | // already. | |||
656 | if (trap_handler::IsThreadInWasm()) { | |||
657 | trap_handler::ClearThreadInWasm(); | |||
658 | } | |||
659 | isolate->thread_local_top()->handler_ = stack_handler.next; | |||
660 | if (saved_js_entry_sp == kNullAddress) { | |||
661 | *isolate->js_entry_sp_address() = saved_js_entry_sp; | |||
662 | } | |||
663 | *isolate->c_entry_fp_address() = saved_c_entry_fp; | |||
664 | } | |||
665 | #endif // V8_ENABLE_WEBASSEMBLY | |||
666 | ||||
667 | } // namespace internal | |||
668 | } // namespace v8 |