1// Copyright 2012 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/api.h"
6
7#include <string.h> // For memcpy, strlen.
8#include <cmath> // For isnan.
9#include <limits>
10#include <vector>
11
12#include "src/api-inl.h"
13
14#include "include/v8-profiler.h"
15#include "include/v8-testing.h"
16#include "include/v8-util.h"
17#include "src/accessors.h"
18#include "src/api-natives.h"
19#include "src/assert-scope.h"
20#include "src/base/functional.h"
21#include "src/base/logging.h"
22#include "src/base/platform/platform.h"
23#include "src/base/platform/time.h"
24#include "src/base/safe_conversions.h"
25#include "src/base/utils/random-number-generator.h"
26#include "src/bootstrapper.h"
27#include "src/builtins/builtins-utils.h"
28#include "src/char-predicates-inl.h"
29#include "src/compiler-dispatcher/compiler-dispatcher.h"
30#include "src/compiler.h"
31#include "src/contexts.h"
32#include "src/conversions-inl.h"
33#include "src/counters.h"
34#include "src/cpu-features.h"
35#include "src/date.h"
36#include "src/debug/debug-coverage.h"
37#include "src/debug/debug-evaluate.h"
38#include "src/debug/debug-type-profile.h"
39#include "src/debug/debug.h"
40#include "src/debug/liveedit.h"
41#include "src/deoptimizer.h"
42#include "src/detachable-vector.h"
43#include "src/execution.h"
44#include "src/frames-inl.h"
45#include "src/gdb-jit.h"
46#include "src/global-handles.h"
47#include "src/globals.h"
48#include "src/heap/heap-inl.h"
49#include "src/icu_util.h"
50#include "src/isolate-inl.h"
51#include "src/json-parser.h"
52#include "src/json-stringifier.h"
53#include "src/messages.h"
54#include "src/microtask-queue.h"
55#include "src/objects-inl.h"
56#include "src/objects/api-callbacks.h"
57#include "src/objects/embedder-data-array-inl.h"
58#include "src/objects/embedder-data-slot-inl.h"
59#include "src/objects/frame-array-inl.h"
60#include "src/objects/hash-table-inl.h"
61#include "src/objects/heap-object.h"
62#include "src/objects/js-array-inl.h"
63#include "src/objects/js-collection-inl.h"
64#include "src/objects/js-generator-inl.h"
65#include "src/objects/js-promise-inl.h"
66#include "src/objects/js-regexp-inl.h"
67#include "src/objects/module-inl.h"
68#include "src/objects/oddball.h"
69#include "src/objects/ordered-hash-table-inl.h"
70#include "src/objects/slots.h"
71#include "src/objects/smi.h"
72#include "src/objects/stack-frame-info-inl.h"
73#include "src/objects/templates.h"
74#include "src/parsing/parse-info.h"
75#include "src/parsing/parser.h"
76#include "src/parsing/scanner-character-streams.h"
77#include "src/pending-compilation-error-handler.h"
78#include "src/profiler/cpu-profiler.h"
79#include "src/profiler/heap-profiler.h"
80#include "src/profiler/heap-snapshot-generator-inl.h"
81#include "src/profiler/profile-generator-inl.h"
82#include "src/profiler/tick-sample.h"
83#include "src/property-descriptor.h"
84#include "src/property-details.h"
85#include "src/property.h"
86#include "src/prototype.h"
87#include "src/runtime-profiler.h"
88#include "src/runtime/runtime.h"
89#include "src/simulator.h"
90#include "src/snapshot/code-serializer.h"
91#include "src/snapshot/natives.h"
92#include "src/snapshot/partial-serializer.h"
93#include "src/snapshot/read-only-serializer.h"
94#include "src/snapshot/snapshot.h"
95#include "src/snapshot/startup-serializer.h"
96#include "src/startup-data-util.h"
97#include "src/string-hasher.h"
98#include "src/tracing/trace-event.h"
99#include "src/trap-handler/trap-handler.h"
100#include "src/unicode-inl.h"
101#include "src/v8.h"
102#include "src/v8threads.h"
103#include "src/value-serializer.h"
104#include "src/version.h"
105#include "src/vm-state-inl.h"
106#include "src/wasm/streaming-decoder.h"
107#include "src/wasm/wasm-engine.h"
108#include "src/wasm/wasm-objects-inl.h"
109#include "src/wasm/wasm-result.h"
110#include "src/wasm/wasm-serialization.h"
111
112#if V8_OS_LINUX || V8_OS_MACOSX
113#include <signal.h>
114#include "include/v8-wasm-trap-handler-posix.h"
115#include "src/trap-handler/handler-inside-posix.h"
116#endif
117
118#if V8_OS_WIN
119#include <versionhelpers.h>
120#include <windows.h>
121#include "include/v8-wasm-trap-handler-win.h"
122#include "src/trap-handler/handler-inside-win.h"
123#if V8_TARGET_ARCH_X64
124#include "src/unwinding-info-win64.h"
125#endif // V8_TARGET_ARCH_X64
126#endif // V8_OS_WIN
127
128namespace v8 {
129
130/*
131 * Most API methods should use one of the three macros:
132 *
133 * ENTER_V8, ENTER_V8_NO_SCRIPT, ENTER_V8_NO_SCRIPT_NO_EXCEPTION.
134 *
135 * The latter two assume that no script is executed, and no exceptions are
136 * scheduled in addition (respectively). Creating a pending exception and
137 * removing it before returning is ok.
138 *
139 * Exceptions should be handled either by invoking one of the
140 * RETURN_ON_FAILED_EXECUTION* macros.
141 *
142 * Don't use macros with DO_NOT_USE in their name.
143 *
144 * TODO(jochen): Document debugger specific macros.
145 * TODO(jochen): Document LOG_API and other RuntimeCallStats macros.
146 * TODO(jochen): All API methods should invoke one of the ENTER_V8* macros.
147 * TODO(jochen): Remove calls form API methods to DO_NOT_USE macros.
148 */
149
150#define LOG_API(isolate, class_name, function_name) \
151 i::RuntimeCallTimerScope _runtime_timer( \
152 isolate, i::RuntimeCallCounterId::kAPI_##class_name##_##function_name); \
153 LOG(isolate, ApiEntryCall("v8::" #class_name "::" #function_name))
154
155#define ENTER_V8_DO_NOT_USE(isolate) i::VMState<v8::OTHER> __state__((isolate))
156
157#define ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, \
158 function_name, bailout_value, \
159 HandleScopeClass, do_callback) \
160 if (IsExecutionTerminatingCheck(isolate)) { \
161 return bailout_value; \
162 } \
163 HandleScopeClass handle_scope(isolate); \
164 CallDepthScope<do_callback> call_depth_scope(isolate, context); \
165 LOG_API(isolate, class_name, function_name); \
166 i::VMState<v8::OTHER> __state__((isolate)); \
167 bool has_pending_exception = false
168
169#define PREPARE_FOR_DEBUG_INTERFACE_EXECUTION_WITH_ISOLATE(isolate, T) \
170 if (IsExecutionTerminatingCheck(isolate)) { \
171 return MaybeLocal<T>(); \
172 } \
173 InternalEscapableScope handle_scope(isolate); \
174 CallDepthScope<false> call_depth_scope(isolate, v8::Local<v8::Context>()); \
175 i::VMState<v8::OTHER> __state__((isolate)); \
176 bool has_pending_exception = false
177
178#define PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \
179 bailout_value, HandleScopeClass, \
180 do_callback) \
181 auto isolate = context.IsEmpty() \
182 ? i::Isolate::Current() \
183 : reinterpret_cast<i::Isolate*>(context->GetIsolate()); \
184 ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \
185 bailout_value, HandleScopeClass, do_callback);
186
187#define PREPARE_FOR_EXECUTION(context, class_name, function_name, T) \
188 PREPARE_FOR_EXECUTION_WITH_CONTEXT(context, class_name, function_name, \
189 MaybeLocal<T>(), InternalEscapableScope, \
190 false)
191
192#define ENTER_V8(isolate, context, class_name, function_name, bailout_value, \
193 HandleScopeClass) \
194 ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \
195 bailout_value, HandleScopeClass, true)
196
197#ifdef DEBUG
198#define ENTER_V8_NO_SCRIPT(isolate, context, class_name, function_name, \
199 bailout_value, HandleScopeClass) \
200 ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \
201 bailout_value, HandleScopeClass, false); \
202 i::DisallowJavascriptExecutionDebugOnly __no_script__((isolate))
203
204#define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \
205 i::VMState<v8::OTHER> __state__((isolate)); \
206 i::DisallowJavascriptExecutionDebugOnly __no_script__((isolate)); \
207 i::DisallowExceptions __no_exceptions__((isolate))
208
209#define ENTER_V8_FOR_NEW_CONTEXT(isolate) \
210 i::VMState<v8::OTHER> __state__((isolate)); \
211 i::DisallowExceptions __no_exceptions__((isolate))
212#else
213#define ENTER_V8_NO_SCRIPT(isolate, context, class_name, function_name, \
214 bailout_value, HandleScopeClass) \
215 ENTER_V8_HELPER_DO_NOT_USE(isolate, context, class_name, function_name, \
216 bailout_value, HandleScopeClass, false)
217
218#define ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate) \
219 i::VMState<v8::OTHER> __state__((isolate));
220
221#define ENTER_V8_FOR_NEW_CONTEXT(isolate) \
222 i::VMState<v8::OTHER> __state__((isolate));
223#endif // DEBUG
224
225#define EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, value) \
226 do { \
227 if (has_pending_exception) { \
228 call_depth_scope.Escape(); \
229 return value; \
230 } \
231 } while (false)
232
233#define RETURN_ON_FAILED_EXECUTION(T) \
234 EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, MaybeLocal<T>())
235
236#define RETURN_ON_FAILED_EXECUTION_PRIMITIVE(T) \
237 EXCEPTION_BAILOUT_CHECK_SCOPED_DO_NOT_USE(isolate, Nothing<T>())
238
239#define RETURN_TO_LOCAL_UNCHECKED(maybe_local, T) \
240 return maybe_local.FromMaybe(Local<T>());
241
242
243#define RETURN_ESCAPED(value) return handle_scope.Escape(value);
244
245namespace {
246
247Local<Context> ContextFromNeverReadOnlySpaceObject(
248 i::Handle<i::JSReceiver> obj) {
249 return reinterpret_cast<v8::Isolate*>(obj->GetIsolate())->GetCurrentContext();
250}
251
252class InternalEscapableScope : public v8::EscapableHandleScope {
253 public:
254 explicit inline InternalEscapableScope(i::Isolate* isolate)
255 : v8::EscapableHandleScope(reinterpret_cast<v8::Isolate*>(isolate)) {}
256};
257
258// TODO(jochen): This should be #ifdef DEBUG
259#ifdef V8_CHECK_MICROTASKS_SCOPES_CONSISTENCY
260void CheckMicrotasksScopesConsistency(i::MicrotaskQueue* microtask_queue) {
261 if (microtask_queue &&
262 microtask_queue->microtasks_policy() == v8::MicrotasksPolicy::kScoped) {
263 DCHECK(microtask_queue->GetMicrotasksScopeDepth() ||
264 !microtask_queue->DebugMicrotasksScopeDepthIsZero());
265 }
266}
267#endif
268
269template <bool do_callback>
270class CallDepthScope {
271 public:
272 explicit CallDepthScope(i::Isolate* isolate, Local<Context> context)
273 : isolate_(isolate),
274 context_(context),
275 escaped_(false),
276 safe_for_termination_(isolate->next_v8_call_is_safe_for_termination()),
277 interrupts_scope_(isolate_, i::StackGuard::TERMINATE_EXECUTION,
278 isolate_->only_terminate_in_safe_scope()
279 ? (safe_for_termination_
280 ? i::InterruptsScope::kRunInterrupts
281 : i::InterruptsScope::kPostponeInterrupts)
282 : i::InterruptsScope::kNoop) {
283 isolate_->handle_scope_implementer()->IncrementCallDepth();
284 isolate_->set_next_v8_call_is_safe_for_termination(false);
285 if (!context.IsEmpty()) {
286 i::Handle<i::Context> env = Utils::OpenHandle(*context);
287 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
288 if (!isolate->context().is_null() &&
289 isolate->context()->native_context() == env->native_context()) {
290 context_ = Local<Context>();
291 } else {
292 impl->SaveContext(isolate->context());
293 isolate->set_context(*env);
294 }
295 }
296 if (do_callback) isolate_->FireBeforeCallEnteredCallback();
297 }
298 ~CallDepthScope() {
299 i::MicrotaskQueue* microtask_queue = isolate_->default_microtask_queue();
300 if (!context_.IsEmpty()) {
301 i::HandleScopeImplementer* impl = isolate_->handle_scope_implementer();
302 isolate_->set_context(impl->RestoreContext());
303
304 i::Handle<i::Context> env = Utils::OpenHandle(*context_);
305 microtask_queue = env->native_context()->microtask_queue();
306 }
307 if (!escaped_) isolate_->handle_scope_implementer()->DecrementCallDepth();
308 if (do_callback) isolate_->FireCallCompletedCallback(microtask_queue);
309// TODO(jochen): This should be #ifdef DEBUG
310#ifdef V8_CHECK_MICROTASKS_SCOPES_CONSISTENCY
311 if (do_callback) CheckMicrotasksScopesConsistency(microtask_queue);
312#endif
313 isolate_->set_next_v8_call_is_safe_for_termination(safe_for_termination_);
314 }
315
316 void Escape() {
317 DCHECK(!escaped_);
318 escaped_ = true;
319 auto handle_scope_implementer = isolate_->handle_scope_implementer();
320 handle_scope_implementer->DecrementCallDepth();
321 bool clear_exception =
322 handle_scope_implementer->CallDepthIsZero() &&
323 isolate_->thread_local_top()->try_catch_handler_ == nullptr;
324 isolate_->OptionalRescheduleException(clear_exception);
325 }
326
327 private:
328 i::Isolate* const isolate_;
329 Local<Context> context_;
330 bool escaped_;
331 bool do_callback_;
332 bool safe_for_termination_;
333 i::InterruptsScope interrupts_scope_;
334};
335
336} // namespace
337
338
339static ScriptOrigin GetScriptOriginForScript(i::Isolate* isolate,
340 i::Handle<i::Script> script) {
341 i::Handle<i::Object> scriptName(script->GetNameOrSourceURL(), isolate);
342 i::Handle<i::Object> source_map_url(script->source_mapping_url(), isolate);
343 i::Handle<i::FixedArray> host_defined_options(script->host_defined_options(),
344 isolate);
345 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
346 ScriptOriginOptions options(script->origin_options());
347 v8::ScriptOrigin origin(
348 Utils::ToLocal(scriptName),
349 v8::Integer::New(v8_isolate, script->line_offset()),
350 v8::Integer::New(v8_isolate, script->column_offset()),
351 v8::Boolean::New(v8_isolate, options.IsSharedCrossOrigin()),
352 v8::Integer::New(v8_isolate, script->id()),
353 Utils::ToLocal(source_map_url),
354 v8::Boolean::New(v8_isolate, options.IsOpaque()),
355 v8::Boolean::New(v8_isolate, script->type() == i::Script::TYPE_WASM),
356 v8::Boolean::New(v8_isolate, options.IsModule()),
357 Utils::ToLocal(host_defined_options));
358 return origin;
359}
360
361
362// --- E x c e p t i o n B e h a v i o r ---
363
364void i::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location) {
365 i::V8::FatalProcessOutOfMemory(isolate, location, false);
366}
367
368// When V8 cannot allocate memory FatalProcessOutOfMemory is called. The default
369// OOM error handler is called and execution is stopped.
370void i::V8::FatalProcessOutOfMemory(i::Isolate* isolate, const char* location,
371 bool is_heap_oom) {
372 char last_few_messages[Heap::kTraceRingBufferSize + 1];
373 char js_stacktrace[Heap::kStacktraceBufferSize + 1];
374 i::HeapStats heap_stats;
375
376 if (isolate == nullptr) {
377 isolate = Isolate::TryGetCurrent();
378 }
379
380 if (isolate == nullptr) {
381 // If the Isolate is not available for the current thread we cannot retrieve
382 // memory information from the Isolate. Write easy-to-recognize values on
383 // the stack.
384 memset(last_few_messages, 0x0BADC0DE, Heap::kTraceRingBufferSize + 1);
385 memset(js_stacktrace, 0x0BADC0DE, Heap::kStacktraceBufferSize + 1);
386 memset(&heap_stats, 0xBADC0DE, sizeof(heap_stats));
387 // Note that the embedder's oom handler is also not available and therefore
388 // won't be called in this case. We just crash.
389 FATAL("Fatal process out of memory: %s", location);
390 UNREACHABLE();
391 }
392
393 memset(last_few_messages, 0, Heap::kTraceRingBufferSize + 1);
394 memset(js_stacktrace, 0, Heap::kStacktraceBufferSize + 1);
395
396 intptr_t start_marker;
397 heap_stats.start_marker = &start_marker;
398 size_t ro_space_size;
399 heap_stats.ro_space_size = &ro_space_size;
400 size_t ro_space_capacity;
401 heap_stats.ro_space_capacity = &ro_space_capacity;
402 size_t new_space_size;
403 heap_stats.new_space_size = &new_space_size;
404 size_t new_space_capacity;
405 heap_stats.new_space_capacity = &new_space_capacity;
406 size_t old_space_size;
407 heap_stats.old_space_size = &old_space_size;
408 size_t old_space_capacity;
409 heap_stats.old_space_capacity = &old_space_capacity;
410 size_t code_space_size;
411 heap_stats.code_space_size = &code_space_size;
412 size_t code_space_capacity;
413 heap_stats.code_space_capacity = &code_space_capacity;
414 size_t map_space_size;
415 heap_stats.map_space_size = &map_space_size;
416 size_t map_space_capacity;
417 heap_stats.map_space_capacity = &map_space_capacity;
418 size_t lo_space_size;
419 heap_stats.lo_space_size = &lo_space_size;
420 size_t code_lo_space_size;
421 heap_stats.code_lo_space_size = &code_lo_space_size;
422 size_t global_handle_count;
423 heap_stats.global_handle_count = &global_handle_count;
424 size_t weak_global_handle_count;
425 heap_stats.weak_global_handle_count = &weak_global_handle_count;
426 size_t pending_global_handle_count;
427 heap_stats.pending_global_handle_count = &pending_global_handle_count;
428 size_t near_death_global_handle_count;
429 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
430 size_t free_global_handle_count;
431 heap_stats.free_global_handle_count = &free_global_handle_count;
432 size_t memory_allocator_size;
433 heap_stats.memory_allocator_size = &memory_allocator_size;
434 size_t memory_allocator_capacity;
435 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
436 size_t malloced_memory;
437 heap_stats.malloced_memory = &malloced_memory;
438 size_t malloced_peak_memory;
439 heap_stats.malloced_peak_memory = &malloced_peak_memory;
440 size_t objects_per_type[LAST_TYPE + 1] = {0};
441 heap_stats.objects_per_type = objects_per_type;
442 size_t size_per_type[LAST_TYPE + 1] = {0};
443 heap_stats.size_per_type = size_per_type;
444 int os_error;
445 heap_stats.os_error = &os_error;
446 heap_stats.last_few_messages = last_few_messages;
447 heap_stats.js_stacktrace = js_stacktrace;
448 intptr_t end_marker;
449 heap_stats.end_marker = &end_marker;
450 if (isolate->heap()->HasBeenSetUp()) {
451 // BUG(1718): Don't use the take_snapshot since we don't support
452 // HeapIterator here without doing a special GC.
453 isolate->heap()->RecordStats(&heap_stats, false);
454 char* first_newline = strchr(last_few_messages, '\n');
455 if (first_newline == nullptr || first_newline[1] == '\0')
456 first_newline = last_few_messages;
457 PrintF("\n<--- Last few GCs --->\n%s\n", first_newline);
458 PrintF("\n<--- JS stacktrace --->\n%s\n", js_stacktrace);
459 }
460 Utils::ReportOOMFailure(isolate, location, is_heap_oom);
461 // If the fatal error handler returns, we stop execution.
462 FATAL("API fatal error handler returned after process out of memory");
463}
464
465
466void Utils::ReportApiFailure(const char* location, const char* message) {
467 i::Isolate* isolate = i::Isolate::Current();
468 FatalErrorCallback callback = nullptr;
469 if (isolate != nullptr) {
470 callback = isolate->exception_behavior();
471 }
472 if (callback == nullptr) {
473 base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location,
474 message);
475 base::OS::Abort();
476 } else {
477 callback(location, message);
478 }
479 isolate->SignalFatalError();
480}
481
482void Utils::ReportOOMFailure(i::Isolate* isolate, const char* location,
483 bool is_heap_oom) {
484 OOMErrorCallback oom_callback = isolate->oom_behavior();
485 if (oom_callback == nullptr) {
486 // TODO(wfh): Remove this fallback once Blink is setting OOM handler. See
487 // crbug.com/614440.
488 FatalErrorCallback fatal_callback = isolate->exception_behavior();
489 if (fatal_callback == nullptr) {
490 base::OS::PrintError("\n#\n# Fatal %s OOM in %s\n#\n\n",
491 is_heap_oom ? "javascript" : "process", location);
492 base::OS::Abort();
493 } else {
494 fatal_callback(location,
495 is_heap_oom
496 ? "Allocation failed - JavaScript heap out of memory"
497 : "Allocation failed - process out of memory");
498 }
499 } else {
500 oom_callback(location, is_heap_oom);
501 }
502 isolate->SignalFatalError();
503}
504
505static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
506 if (isolate->has_scheduled_exception()) {
507 return isolate->scheduled_exception() ==
508 i::ReadOnlyRoots(isolate).termination_exception();
509 }
510 return false;
511}
512
513
514void V8::SetNativesDataBlob(StartupData* natives_blob) {
515 i::V8::SetNativesBlob(natives_blob);
516}
517
518
519void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
520 i::V8::SetSnapshotBlob(snapshot_blob);
521}
522
523namespace {
524
525class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
526 public:
527 void* Allocate(size_t length) override {
528#if V8_OS_AIX && _LINUX_SOURCE_COMPAT
529 // Work around for GCC bug on AIX
530 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
531 void* data = __linux_calloc(length, 1);
532#else
533 void* data = calloc(length, 1);
534#endif
535 return data;
536 }
537
538 void* AllocateUninitialized(size_t length) override {
539#if V8_OS_AIX && _LINUX_SOURCE_COMPAT
540 // Work around for GCC bug on AIX
541 // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79839
542 void* data = __linux_malloc(length);
543#else
544 void* data = malloc(length);
545#endif
546 return data;
547 }
548
549 void Free(void* data, size_t) override { free(data); }
550};
551
552struct SnapshotCreatorData {
553 explicit SnapshotCreatorData(Isolate* isolate)
554 : isolate_(isolate),
555 default_context_(),
556 contexts_(isolate),
557 created_(false) {}
558
559 static SnapshotCreatorData* cast(void* data) {
560 return reinterpret_cast<SnapshotCreatorData*>(data);
561 }
562
563 ArrayBufferAllocator allocator_;
564 Isolate* isolate_;
565 Persistent<Context> default_context_;
566 SerializeInternalFieldsCallback default_embedder_fields_serializer_;
567 PersistentValueVector<Context> contexts_;
568 std::vector<SerializeInternalFieldsCallback> embedder_fields_serializers_;
569 bool created_;
570};
571
572} // namespace
573
574SnapshotCreator::SnapshotCreator(Isolate* isolate,
575 const intptr_t* external_references,
576 StartupData* existing_snapshot) {
577 SnapshotCreatorData* data = new SnapshotCreatorData(isolate);
578 data->isolate_ = isolate;
579 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
580 internal_isolate->set_array_buffer_allocator(&data->allocator_);
581 internal_isolate->set_api_external_references(external_references);
582 internal_isolate->enable_serializer();
583 isolate->Enter();
584 const StartupData* blob = existing_snapshot
585 ? existing_snapshot
586 : i::Snapshot::DefaultSnapshotBlob();
587 if (blob && blob->raw_size > 0) {
588 internal_isolate->set_snapshot_blob(blob);
589 i::Snapshot::Initialize(internal_isolate);
590 } else {
591 internal_isolate->InitWithoutSnapshot();
592 }
593 data_ = data;
594}
595
596SnapshotCreator::SnapshotCreator(const intptr_t* external_references,
597 StartupData* existing_snapshot)
598 : SnapshotCreator(Isolate::Allocate(), external_references,
599 existing_snapshot) {}
600
601SnapshotCreator::~SnapshotCreator() {
602 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
603 DCHECK(data->created_);
604 Isolate* isolate = data->isolate_;
605 isolate->Exit();
606 isolate->Dispose();
607 delete data;
608}
609
610Isolate* SnapshotCreator::GetIsolate() {
611 return SnapshotCreatorData::cast(data_)->isolate_;
612}
613
614void SnapshotCreator::SetDefaultContext(
615 Local<Context> context, SerializeInternalFieldsCallback callback) {
616 DCHECK(!context.IsEmpty());
617 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
618 DCHECK(!data->created_);
619 DCHECK(data->default_context_.IsEmpty());
620 Isolate* isolate = data->isolate_;
621 CHECK_EQ(isolate, context->GetIsolate());
622 data->default_context_.Reset(isolate, context);
623 data->default_embedder_fields_serializer_ = callback;
624}
625
626size_t SnapshotCreator::AddContext(Local<Context> context,
627 SerializeInternalFieldsCallback callback) {
628 DCHECK(!context.IsEmpty());
629 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
630 DCHECK(!data->created_);
631 Isolate* isolate = data->isolate_;
632 CHECK_EQ(isolate, context->GetIsolate());
633 size_t index = data->contexts_.Size();
634 data->contexts_.Append(context);
635 data->embedder_fields_serializers_.push_back(callback);
636 return index;
637}
638
639size_t SnapshotCreator::AddTemplate(Local<Template> template_obj) {
640 return AddData(template_obj);
641}
642
643size_t SnapshotCreator::AddData(i::Address object) {
644 DCHECK_NE(object, i::kNullAddress);
645 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
646 DCHECK(!data->created_);
647 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
648 i::HandleScope scope(isolate);
649 i::Handle<i::Object> obj(i::Object(object), isolate);
650 i::Handle<i::ArrayList> list;
651 if (!isolate->heap()->serialized_objects()->IsArrayList()) {
652 list = i::ArrayList::New(isolate, 1);
653 } else {
654 list = i::Handle<i::ArrayList>(
655 i::ArrayList::cast(isolate->heap()->serialized_objects()), isolate);
656 }
657 size_t index = static_cast<size_t>(list->Length());
658 list = i::ArrayList::Add(isolate, list, obj);
659 isolate->heap()->SetSerializedObjects(*list);
660 return index;
661}
662
663size_t SnapshotCreator::AddData(Local<Context> context, i::Address object) {
664 DCHECK_NE(object, i::kNullAddress);
665 DCHECK(!SnapshotCreatorData::cast(data_)->created_);
666 i::Handle<i::Context> ctx = Utils::OpenHandle(*context);
667 i::Isolate* isolate = ctx->GetIsolate();
668 i::HandleScope scope(isolate);
669 i::Handle<i::Object> obj(i::Object(object), isolate);
670 i::Handle<i::ArrayList> list;
671 if (!ctx->serialized_objects()->IsArrayList()) {
672 list = i::ArrayList::New(isolate, 1);
673 } else {
674 list = i::Handle<i::ArrayList>(
675 i::ArrayList::cast(ctx->serialized_objects()), isolate);
676 }
677 size_t index = static_cast<size_t>(list->Length());
678 list = i::ArrayList::Add(isolate, list, obj);
679 ctx->set_serialized_objects(*list);
680 return index;
681}
682
683namespace {
684void ConvertSerializedObjectsToFixedArray(Local<Context> context) {
685 i::Handle<i::Context> ctx = Utils::OpenHandle(*context);
686 i::Isolate* isolate = ctx->GetIsolate();
687 if (!ctx->serialized_objects()->IsArrayList()) {
688 ctx->set_serialized_objects(i::ReadOnlyRoots(isolate).empty_fixed_array());
689 } else {
690 i::Handle<i::ArrayList> list(i::ArrayList::cast(ctx->serialized_objects()),
691 isolate);
692 i::Handle<i::FixedArray> elements = i::ArrayList::Elements(isolate, list);
693 ctx->set_serialized_objects(*elements);
694 }
695}
696
697void ConvertSerializedObjectsToFixedArray(i::Isolate* isolate) {
698 if (!isolate->heap()->serialized_objects()->IsArrayList()) {
699 isolate->heap()->SetSerializedObjects(
700 i::ReadOnlyRoots(isolate).empty_fixed_array());
701 } else {
702 i::Handle<i::ArrayList> list(
703 i::ArrayList::cast(isolate->heap()->serialized_objects()), isolate);
704 i::Handle<i::FixedArray> elements = i::ArrayList::Elements(isolate, list);
705 isolate->heap()->SetSerializedObjects(*elements);
706 }
707}
708} // anonymous namespace
709
710StartupData SnapshotCreator::CreateBlob(
711 SnapshotCreator::FunctionCodeHandling function_code_handling) {
712 SnapshotCreatorData* data = SnapshotCreatorData::cast(data_);
713 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(data->isolate_);
714 DCHECK(!data->created_);
715 DCHECK(!data->default_context_.IsEmpty());
716
717 int num_additional_contexts = static_cast<int>(data->contexts_.Size());
718
719 {
720 i::HandleScope scope(isolate);
721 // Convert list of context-independent data to FixedArray.
722 ConvertSerializedObjectsToFixedArray(isolate);
723
724 // Convert lists of context-dependent data to FixedArray.
725 ConvertSerializedObjectsToFixedArray(
726 data->default_context_.Get(data->isolate_));
727 for (int i = 0; i < num_additional_contexts; i++) {
728 ConvertSerializedObjectsToFixedArray(data->contexts_.Get(i));
729 }
730
731 // We need to store the global proxy size upfront in case we need the
732 // bootstrapper to create a global proxy before we deserialize the context.
733 i::Handle<i::FixedArray> global_proxy_sizes =
734 isolate->factory()->NewFixedArray(num_additional_contexts,
735 i::AllocationType::kOld);
736 for (int i = 0; i < num_additional_contexts; i++) {
737 i::Handle<i::Context> context =
738 v8::Utils::OpenHandle(*data->contexts_.Get(i));
739 global_proxy_sizes->set(i,
740 i::Smi::FromInt(context->global_proxy()->Size()));
741 }
742 isolate->heap()->SetSerializedGlobalProxySizes(*global_proxy_sizes);
743 }
744
745 // We might rehash strings and re-sort descriptors. Clear the lookup cache.
746 isolate->descriptor_lookup_cache()->Clear();
747
748 // If we don't do this then we end up with a stray root pointing at the
749 // context even after we have disposed of the context.
750 isolate->heap()->CollectAllAvailableGarbage(
751 i::GarbageCollectionReason::kSnapshotCreator);
752 {
753 i::HandleScope scope(isolate);
754 isolate->heap()->CompactWeakArrayLists(internal::AllocationType::kOld);
755 }
756
757 isolate->heap()->read_only_space()->ClearStringPaddingIfNeeded();
758
759 if (function_code_handling == FunctionCodeHandling::kClear) {
760 // Clear out re-compilable data from all shared function infos. Any
761 // JSFunctions using these SFIs will have their code pointers reset by the
762 // partial serializer.
763 //
764 // We have to iterate the heap and collect handles to each clearable SFI,
765 // before we disable allocation, since we have to allocate UncompiledDatas
766 // to be able to recompile them.
767 //
768 // Compiled irregexp code is also flushed by collecting and clearing any
769 // seen JSRegExp objects.
770 i::HandleScope scope(isolate);
771 std::vector<i::Handle<i::SharedFunctionInfo>> sfis_to_clear;
772
773 { // Heap allocation is disallowed within this scope.
774 i::HeapIterator heap_iterator(isolate->heap());
775 for (i::HeapObject current_obj = heap_iterator.next();
776 !current_obj.is_null(); current_obj = heap_iterator.next()) {
777 if (current_obj->IsSharedFunctionInfo()) {
778 i::SharedFunctionInfo shared =
779 i::SharedFunctionInfo::cast(current_obj);
780 if (shared->CanDiscardCompiled()) {
781 sfis_to_clear.emplace_back(shared, isolate);
782 }
783 } else if (current_obj->IsJSRegExp()) {
784 i::JSRegExp regexp = i::JSRegExp::cast(current_obj);
785 if (regexp->HasCompiledCode()) {
786 regexp->DiscardCompiledCodeForSerialization();
787 }
788 }
789 }
790 }
791
792 // Must happen after heap iteration since SFI::DiscardCompiled may allocate.
793 for (i::Handle<i::SharedFunctionInfo> shared : sfis_to_clear) {
794 i::SharedFunctionInfo::DiscardCompiled(isolate, shared);
795 }
796 }
797
798 i::DisallowHeapAllocation no_gc_from_here_on;
799
800 int num_contexts = num_additional_contexts + 1;
801 std::vector<i::Context> contexts;
802 contexts.reserve(num_contexts);
803 {
804 i::HandleScope scope(isolate);
805 contexts.push_back(
806 *v8::Utils::OpenHandle(*data->default_context_.Get(data->isolate_)));
807 data->default_context_.Reset();
808 for (int i = 0; i < num_additional_contexts; i++) {
809 i::Handle<i::Context> context =
810 v8::Utils::OpenHandle(*data->contexts_.Get(i));
811 contexts.push_back(*context);
812 }
813 data->contexts_.Clear();
814 }
815
816 // Check that values referenced by global/eternal handles are accounted for.
817 i::SerializedHandleChecker handle_checker(isolate, &contexts);
818 CHECK(handle_checker.CheckGlobalAndEternalHandles());
819
820 i::HeapIterator heap_iterator(isolate->heap());
821 for (i::HeapObject current_obj = heap_iterator.next(); !current_obj.is_null();
822 current_obj = heap_iterator.next()) {
823 if (current_obj->IsJSFunction()) {
824 i::JSFunction fun = i::JSFunction::cast(current_obj);
825
826 // Complete in-object slack tracking for all functions.
827 fun->CompleteInobjectSlackTrackingIfActive();
828
829 // Also, clear out feedback vectors, or any optimized code.
830 if (!fun->raw_feedback_cell()->value()->IsUndefined()) {
831 fun->raw_feedback_cell()->set_value(
832 i::ReadOnlyRoots(isolate).undefined_value());
833 fun->set_code(isolate->builtins()->builtin(i::Builtins::kCompileLazy));
834 }
835 if (function_code_handling == FunctionCodeHandling::kClear) {
836 DCHECK(fun->shared()->HasWasmExportedFunctionData() ||
837 fun->shared()->HasBuiltinId() ||
838 fun->shared()->IsApiFunction() ||
839 fun->shared()->HasUncompiledDataWithoutPreparseData());
840 }
841 }
842 }
843
844 i::ReadOnlySerializer read_only_serializer(isolate);
845 read_only_serializer.SerializeReadOnlyRoots();
846
847 i::StartupSerializer startup_serializer(isolate, &read_only_serializer);
848 startup_serializer.SerializeStrongReferences();
849
850 // Serialize each context with a new partial serializer.
851 std::vector<i::SnapshotData*> context_snapshots;
852 context_snapshots.reserve(num_contexts);
853
854 // TODO(6593): generalize rehashing, and remove this flag.
855 bool can_be_rehashed = true;
856
857 for (int i = 0; i < num_contexts; i++) {
858 bool is_default_context = i == 0;
859 i::PartialSerializer partial_serializer(
860 isolate, &startup_serializer,
861 is_default_context ? data->default_embedder_fields_serializer_
862 : data->embedder_fields_serializers_[i - 1]);
863 partial_serializer.Serialize(&contexts[i], !is_default_context);
864 can_be_rehashed = can_be_rehashed && partial_serializer.can_be_rehashed();
865 context_snapshots.push_back(new i::SnapshotData(&partial_serializer));
866 }
867
868 startup_serializer.SerializeWeakReferencesAndDeferred();
869 can_be_rehashed = can_be_rehashed && startup_serializer.can_be_rehashed();
870
871 read_only_serializer.FinalizeSerialization();
872 can_be_rehashed = can_be_rehashed && read_only_serializer.can_be_rehashed();
873
874 i::SnapshotData read_only_snapshot(&read_only_serializer);
875 i::SnapshotData startup_snapshot(&startup_serializer);
876 StartupData result =
877 i::Snapshot::CreateSnapshotBlob(&startup_snapshot, &read_only_snapshot,
878 context_snapshots, can_be_rehashed);
879
880 // Delete heap-allocated context snapshot instances.
881 for (const auto context_snapshot : context_snapshots) {
882 delete context_snapshot;
883 }
884 data->created_ = true;
885
886 DCHECK(i::Snapshot::VerifyChecksum(&result));
887 return result;
888}
889
890void V8::SetDcheckErrorHandler(DcheckErrorCallback that) {
891 v8::base::SetDcheckFunction(that);
892}
893
894void V8::SetFlagsFromString(const char* str, int length) {
895 i::FlagList::SetFlagsFromString(str, length);
896 i::FlagList::EnforceFlagImplications();
897}
898
899
900void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
901 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
902}
903
904RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
905
906RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
907 : extension_(std::move(extension)) {}
908
909// static
910void RegisteredExtension::Register(std::unique_ptr<Extension> extension) {
911 RegisteredExtension* new_extension =
912 new RegisteredExtension(std::move(extension));
913 new_extension->next_ = first_extension_;
914 first_extension_ = new_extension;
915}
916
917// static
918void RegisteredExtension::UnregisterAll() {
919 RegisteredExtension* re = first_extension_;
920 while (re != nullptr) {
921 RegisteredExtension* next = re->next();
922 delete re;
923 re = next;
924 }
925 first_extension_ = nullptr;
926}
927
928namespace {
929class ExtensionResource : public String::ExternalOneByteStringResource {
930 public:
931 ExtensionResource() : data_(nullptr), length_(0) {}
932 ExtensionResource(const char* data, size_t length)
933 : data_(data), length_(length) {}
934 const char* data() const override { return data_; }
935 size_t length() const override { return length_; }
936 void Dispose() override {}
937
938 private:
939 const char* data_;
940 size_t length_;
941};
942} // anonymous namespace
943
944void RegisterExtension(std::unique_ptr<Extension> extension) {
945 RegisteredExtension::Register(std::move(extension));
946}
947
948Extension::Extension(const char* name,
949 const char* source,
950 int dep_count,
951 const char** deps,
952 int source_length)
953 : name_(name),
954 source_length_(source_length >= 0 ?
955 source_length :
956 (source ? static_cast<int>(strlen(source)) : 0)),
957 dep_count_(dep_count),
958 deps_(deps),
959 auto_enable_(false) {
960 source_ = new ExtensionResource(source, source_length_);
961 CHECK(source != nullptr || source_length_ == 0);
962}
963
964ResourceConstraints::ResourceConstraints()
965 : max_semi_space_size_in_kb_(0),
966 max_old_space_size_(0),
967 stack_limit_(nullptr),
968 code_range_size_(0),
969 max_zone_pool_size_(0) {}
970
971void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
972 uint64_t virtual_memory_limit) {
973 set_max_semi_space_size_in_kb(
974 i::Heap::ComputeMaxSemiSpaceSize(physical_memory));
975 set_max_old_space_size(i::Heap::ComputeMaxOldGenerationSize(physical_memory));
976
977 if (virtual_memory_limit > 0 && i::kRequiresCodeRange) {
978 // Reserve no more than 1/8 of the memory for the code range, but at most
979 // kMaximalCodeRangeSize.
980 set_code_range_size(
981 i::Min(i::kMaximalCodeRangeSize / i::MB,
982 static_cast<size_t>((virtual_memory_limit >> 3) / i::MB)));
983 }
984}
985
986void SetResourceConstraints(i::Isolate* isolate,
987 const ResourceConstraints& constraints) {
988 size_t semi_space_size = constraints.max_semi_space_size_in_kb();
989 size_t old_space_size = constraints.max_old_space_size();
990 size_t code_range_size = constraints.code_range_size();
991 if (semi_space_size != 0 || old_space_size != 0 || code_range_size != 0) {
992 isolate->heap()->ConfigureHeap(semi_space_size, old_space_size,
993 code_range_size);
994 }
995
996 if (constraints.stack_limit() != nullptr) {
997 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints.stack_limit());
998 isolate->stack_guard()->SetStackLimit(limit);
999 }
1000}
1001
1002i::Address* V8::GlobalizeReference(i::Isolate* isolate, i::Address* obj) {
1003 LOG_API(isolate, Persistent, New);
1004 i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
1005#ifdef VERIFY_HEAP
1006 if (i::FLAG_verify_heap) {
1007 i::Object(*obj)->ObjectVerify(isolate);
1008 }
1009#endif // VERIFY_HEAP
1010 return result.location();
1011}
1012
1013i::Address* V8::GlobalizeTracedReference(i::Isolate* isolate, i::Address* obj,
1014 internal::Address* slot) {
1015 LOG_API(isolate, TracedGlobal, New);
1016 i::Handle<i::Object> result =
1017 isolate->global_handles()->CreateTraced(*obj, slot);
1018#ifdef VERIFY_HEAP
1019 if (i::FLAG_verify_heap) {
1020 i::Object(*obj)->ObjectVerify(isolate);
1021 }
1022#endif // VERIFY_HEAP
1023 return result.location();
1024}
1025
1026i::Address* V8::CopyGlobalReference(i::Address* from) {
1027 i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(from);
1028 return result.location();
1029}
1030
1031void V8::MoveGlobalReference(internal::Address** from, internal::Address** to) {
1032 i::GlobalHandles::MoveGlobal(from, to);
1033}
1034
1035void V8::MoveTracedGlobalReference(internal::Address** from,
1036 internal::Address** to) {
1037 i::GlobalHandles::MoveTracedGlobal(from, to);
1038}
1039
1040void V8::RegisterExternallyReferencedObject(i::Address* location,
1041 i::Isolate* isolate) {
1042 isolate->heap()->RegisterExternallyReferencedObject(location);
1043}
1044
1045void V8::MakeWeak(i::Address* location, void* parameter,
1046 WeakCallbackInfo<void>::Callback weak_callback,
1047 WeakCallbackType type) {
1048 i::GlobalHandles::MakeWeak(location, parameter, weak_callback, type);
1049}
1050
1051void V8::MakeWeak(i::Address** location_addr) {
1052 i::GlobalHandles::MakeWeak(location_addr);
1053}
1054
1055void* V8::ClearWeak(i::Address* location) {
1056 return i::GlobalHandles::ClearWeakness(location);
1057}
1058
1059void V8::AnnotateStrongRetainer(i::Address* location, const char* label) {
1060 i::GlobalHandles::AnnotateStrongRetainer(location, label);
1061}
1062
1063void V8::DisposeGlobal(i::Address* location) {
1064 i::GlobalHandles::Destroy(location);
1065}
1066
1067void V8::DisposeTracedGlobal(internal::Address* location) {
1068 i::GlobalHandles::DestroyTraced(location);
1069}
1070
1071void V8::SetFinalizationCallbackTraced(
1072 internal::Address* location, void* parameter,
1073 WeakCallbackInfo<void>::Callback callback) {
1074 i::GlobalHandles::SetFinalizationCallbackForTraced(location, parameter,
1075 callback);
1076}
1077
1078Value* V8::Eternalize(Isolate* v8_isolate, Value* value) {
1079 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1080 i::Object object = *Utils::OpenHandle(value);
1081 int index = -1;
1082 isolate->eternal_handles()->Create(isolate, object, &index);
1083 return reinterpret_cast<Value*>(
1084 isolate->eternal_handles()->Get(index).location());
1085}
1086
1087
1088void V8::FromJustIsNothing() {
1089 Utils::ApiCheck(false, "v8::FromJust", "Maybe value is Nothing.");
1090}
1091
1092
1093void V8::ToLocalEmpty() {
1094 Utils::ApiCheck(false, "v8::ToLocalChecked", "Empty MaybeLocal.");
1095}
1096
1097void V8::InternalFieldOutOfBounds(int index) {
1098 Utils::ApiCheck(0 <= index && index < kInternalFieldsInWeakCallback,
1099 "WeakCallbackInfo::GetInternalField",
1100 "Internal field out of bounds.");
1101}
1102
1103
1104// --- H a n d l e s ---
1105
1106
1107HandleScope::HandleScope(Isolate* isolate) {
1108 Initialize(isolate);
1109}
1110
1111
1112void HandleScope::Initialize(Isolate* isolate) {
1113 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
1114 // We do not want to check the correct usage of the Locker class all over the
1115 // place, so we do it only here: Without a HandleScope, an embedder can do
1116 // almost nothing, so it is enough to check in this central place.
1117 // We make an exception if the serializer is enabled, which means that the
1118 // Isolate is exclusively used to create a snapshot.
1119 Utils::ApiCheck(
1120 !v8::Locker::IsActive() ||
1121 internal_isolate->thread_manager()->IsLockedByCurrentThread() ||
1122 internal_isolate->serializer_enabled(),
1123 "HandleScope::HandleScope",
1124 "Entering the V8 API without proper locking in place");
1125 i::HandleScopeData* current = internal_isolate->handle_scope_data();
1126 isolate_ = internal_isolate;
1127 prev_next_ = current->next;
1128 prev_limit_ = current->limit;
1129 current->level++;
1130}
1131
1132
1133HandleScope::~HandleScope() {
1134 i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
1135}
1136
1137void* HandleScope::operator new(size_t) { base::OS::Abort(); }
1138void* HandleScope::operator new[](size_t) { base::OS::Abort(); }
1139void HandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
1140void HandleScope::operator delete[](void*, size_t) { base::OS::Abort(); }
1141
1142int HandleScope::NumberOfHandles(Isolate* isolate) {
1143 return i::HandleScope::NumberOfHandles(
1144 reinterpret_cast<i::Isolate*>(isolate));
1145}
1146
1147i::Address* HandleScope::CreateHandle(i::Isolate* isolate, i::Address value) {
1148 return i::HandleScope::CreateHandle(isolate, value);
1149}
1150
1151EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
1152 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1153 escape_slot_ =
1154 CreateHandle(isolate, i::ReadOnlyRoots(isolate).the_hole_value()->ptr());
1155 Initialize(v8_isolate);
1156}
1157
1158i::Address* EscapableHandleScope::Escape(i::Address* escape_value) {
1159 i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap();
1160 Utils::ApiCheck(i::Object(*escape_slot_)->IsTheHole(heap->isolate()),
1161 "EscapableHandleScope::Escape", "Escape value set twice");
1162 if (escape_value == nullptr) {
1163 *escape_slot_ = i::ReadOnlyRoots(heap).undefined_value()->ptr();
1164 return nullptr;
1165 }
1166 *escape_slot_ = *escape_value;
1167 return escape_slot_;
1168}
1169
1170void* EscapableHandleScope::operator new(size_t) { base::OS::Abort(); }
1171void* EscapableHandleScope::operator new[](size_t) { base::OS::Abort(); }
1172void EscapableHandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
1173void EscapableHandleScope::operator delete[](void*, size_t) {
1174 base::OS::Abort();
1175}
1176
1177SealHandleScope::SealHandleScope(Isolate* isolate)
1178 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
1179 i::HandleScopeData* current = isolate_->handle_scope_data();
1180 prev_limit_ = current->limit;
1181 current->limit = current->next;
1182 prev_sealed_level_ = current->sealed_level;
1183 current->sealed_level = current->level;
1184}
1185
1186
1187SealHandleScope::~SealHandleScope() {
1188 i::HandleScopeData* current = isolate_->handle_scope_data();
1189 DCHECK_EQ(current->next, current->limit);
1190 current->limit = prev_limit_;
1191 DCHECK_EQ(current->level, current->sealed_level);
1192 current->sealed_level = prev_sealed_level_;
1193}
1194
1195void* SealHandleScope::operator new(size_t) { base::OS::Abort(); }
1196void* SealHandleScope::operator new[](size_t) { base::OS::Abort(); }
1197void SealHandleScope::operator delete(void*, size_t) { base::OS::Abort(); }
1198void SealHandleScope::operator delete[](void*, size_t) { base::OS::Abort(); }
1199
1200void Context::Enter() {
1201 i::Handle<i::Context> env = Utils::OpenHandle(this);
1202 i::Isolate* isolate = env->GetIsolate();
1203 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1204 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
1205 impl->EnterContext(*env);
1206 impl->SaveContext(isolate->context());
1207 isolate->set_context(*env);
1208}
1209
1210void Context::Exit() {
1211 i::Handle<i::Context> env = Utils::OpenHandle(this);
1212 i::Isolate* isolate = env->GetIsolate();
1213 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1214 i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
1215 if (!Utils::ApiCheck(impl->LastEnteredContextWas(*env), "v8::Context::Exit()",
1216 "Cannot exit non-entered context")) {
1217 return;
1218 }
1219 impl->LeaveContext();
1220 isolate->set_context(impl->RestoreContext());
1221}
1222
1223Context::BackupIncumbentScope::BackupIncumbentScope(
1224 Local<Context> backup_incumbent_context)
1225 : backup_incumbent_context_(backup_incumbent_context) {
1226 DCHECK(!backup_incumbent_context_.IsEmpty());
1227
1228 i::Handle<i::Context> env = Utils::OpenHandle(*backup_incumbent_context_);
1229 i::Isolate* isolate = env->GetIsolate();
1230
1231 js_stack_comparable_address_ =
1232 i::SimulatorStack::RegisterJSStackComparableAddress(isolate);
1233
1234 prev_ = isolate->top_backup_incumbent_scope();
1235 isolate->set_top_backup_incumbent_scope(this);
1236}
1237
1238Context::BackupIncumbentScope::~BackupIncumbentScope() {
1239 i::Handle<i::Context> env = Utils::OpenHandle(*backup_incumbent_context_);
1240 i::Isolate* isolate = env->GetIsolate();
1241
1242 i::SimulatorStack::UnregisterJSStackComparableAddress(isolate);
1243
1244 isolate->set_top_backup_incumbent_scope(prev_);
1245}
1246
1247STATIC_ASSERT(i::Internals::kEmbedderDataSlotSize == i::kEmbedderDataSlotSize);
1248
1249static i::Handle<i::EmbedderDataArray> EmbedderDataFor(Context* context,
1250 int index, bool can_grow,
1251 const char* location) {
1252 i::Handle<i::Context> env = Utils::OpenHandle(context);
1253 i::Isolate* isolate = env->GetIsolate();
1254 bool ok =
1255 Utils::ApiCheck(env->IsNativeContext(),
1256 location,
1257 "Not a native context") &&
1258 Utils::ApiCheck(index >= 0, location, "Negative index");
1259 if (!ok) return i::Handle<i::EmbedderDataArray>();
1260 // TODO(ishell): remove cast once embedder_data slot has a proper type.
1261 i::Handle<i::EmbedderDataArray> data(
1262 i::EmbedderDataArray::cast(env->embedder_data()), isolate);
1263 if (index < data->length()) return data;
1264 if (!Utils::ApiCheck(can_grow && index < i::EmbedderDataArray::kMaxLength,
1265 location, "Index too large")) {
1266 return i::Handle<i::EmbedderDataArray>();
1267 }
1268 data = i::EmbedderDataArray::EnsureCapacity(isolate, data, index);
1269 env->set_embedder_data(*data);
1270 return data;
1271}
1272
1273uint32_t Context::GetNumberOfEmbedderDataFields() {
1274 i::Handle<i::Context> context = Utils::OpenHandle(this);
1275 CHECK(context->IsNativeContext());
1276 // TODO(ishell): remove cast once embedder_data slot has a proper type.
1277 return static_cast<uint32_t>(
1278 i::EmbedderDataArray::cast(context->embedder_data())->length());
1279}
1280
1281v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
1282 const char* location = "v8::Context::GetEmbedderData()";
1283 i::Handle<i::EmbedderDataArray> data =
1284 EmbedderDataFor(this, index, false, location);
1285 if (data.is_null()) return Local<Value>();
1286 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1287 i::Handle<i::Object> result(i::EmbedderDataSlot(*data, index).load_tagged(),
1288 isolate);
1289 return Utils::ToLocal(result);
1290}
1291
1292
1293void Context::SetEmbedderData(int index, v8::Local<Value> value) {
1294 const char* location = "v8::Context::SetEmbedderData()";
1295 i::Handle<i::EmbedderDataArray> data =
1296 EmbedderDataFor(this, index, true, location);
1297 if (data.is_null()) return;
1298 i::Handle<i::Object> val = Utils::OpenHandle(*value);
1299 i::EmbedderDataSlot::store_tagged(*data, index, *val);
1300 DCHECK_EQ(*Utils::OpenHandle(*value),
1301 *Utils::OpenHandle(*GetEmbedderData(index)));
1302}
1303
1304
1305void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
1306 const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
1307 i::Handle<i::EmbedderDataArray> data =
1308 EmbedderDataFor(this, index, false, location);
1309 if (data.is_null()) return nullptr;
1310 void* result;
1311 Utils::ApiCheck(i::EmbedderDataSlot(*data, index).ToAlignedPointer(&result),
1312 location, "Pointer is not aligned");
1313 return result;
1314}
1315
1316
1317void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
1318 const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
1319 i::Handle<i::EmbedderDataArray> data =
1320 EmbedderDataFor(this, index, true, location);
1321 bool ok = i::EmbedderDataSlot(*data, index).store_aligned_pointer(value);
1322 Utils::ApiCheck(ok, location, "Pointer is not aligned");
1323 DCHECK_EQ(value, GetAlignedPointerFromEmbedderData(index));
1324}
1325
1326
1327// --- T e m p l a t e ---
1328
1329
1330static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
1331 that->set_number_of_properties(0);
1332 that->set_tag(i::Smi::FromInt(type));
1333}
1334
1335
1336void Template::Set(v8::Local<Name> name, v8::Local<Data> value,
1337 v8::PropertyAttribute attribute) {
1338 auto templ = Utils::OpenHandle(this);
1339 i::Isolate* isolate = templ->GetIsolate();
1340 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1341 i::HandleScope scope(isolate);
1342 auto value_obj = Utils::OpenHandle(*value);
1343 CHECK(!value_obj->IsJSReceiver() || value_obj->IsTemplateInfo());
1344 if (value_obj->IsObjectTemplateInfo()) {
1345 templ->set_serial_number(i::Smi::kZero);
1346 if (templ->IsFunctionTemplateInfo()) {
1347 i::Handle<i::FunctionTemplateInfo>::cast(templ)->set_do_not_cache(true);
1348 }
1349 }
1350 i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
1351 value_obj,
1352 static_cast<i::PropertyAttributes>(attribute));
1353}
1354
1355void Template::SetPrivate(v8::Local<Private> name, v8::Local<Data> value,
1356 v8::PropertyAttribute attribute) {
1357 Set(Utils::ToLocal(Utils::OpenHandle(reinterpret_cast<Name*>(*name))), value,
1358 attribute);
1359}
1360
1361void Template::SetAccessorProperty(
1362 v8::Local<v8::Name> name,
1363 v8::Local<FunctionTemplate> getter,
1364 v8::Local<FunctionTemplate> setter,
1365 v8::PropertyAttribute attribute,
1366 v8::AccessControl access_control) {
1367 // TODO(verwaest): Remove |access_control|.
1368 DCHECK_EQ(v8::DEFAULT, access_control);
1369 auto templ = Utils::OpenHandle(this);
1370 auto isolate = templ->GetIsolate();
1371 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1372 DCHECK(!name.IsEmpty());
1373 DCHECK(!getter.IsEmpty() || !setter.IsEmpty());
1374 i::HandleScope scope(isolate);
1375 i::ApiNatives::AddAccessorProperty(
1376 isolate, templ, Utils::OpenHandle(*name),
1377 Utils::OpenHandle(*getter, true), Utils::OpenHandle(*setter, true),
1378 static_cast<i::PropertyAttributes>(attribute));
1379}
1380
1381
1382// --- F u n c t i o n T e m p l a t e ---
1383static void InitializeFunctionTemplate(
1384 i::Handle<i::FunctionTemplateInfo> info) {
1385 InitializeTemplate(info, Consts::FUNCTION_TEMPLATE);
1386 info->set_flag(0);
1387}
1388
1389static Local<ObjectTemplate> ObjectTemplateNew(
1390 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor,
1391 bool do_not_cache);
1392
1393Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
1394 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
1395 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1396 i::Handle<i::Object> result(Utils::OpenHandle(this)->GetPrototypeTemplate(),
1397 i_isolate);
1398 if (result->IsUndefined(i_isolate)) {
1399 // Do not cache prototype objects.
1400 result = Utils::OpenHandle(
1401 *ObjectTemplateNew(i_isolate, Local<FunctionTemplate>(), true));
1402 i::FunctionTemplateInfo::SetPrototypeTemplate(
1403 i_isolate, Utils::OpenHandle(this), result);
1404 }
1405 return ToApiHandle<ObjectTemplate>(result);
1406}
1407
1408void FunctionTemplate::SetPrototypeProviderTemplate(
1409 Local<FunctionTemplate> prototype_provider) {
1410 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
1411 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1412 i::Handle<i::Object> result = Utils::OpenHandle(*prototype_provider);
1413 auto info = Utils::OpenHandle(this);
1414 CHECK(info->GetPrototypeTemplate()->IsUndefined(i_isolate));
1415 CHECK(info->GetParentTemplate()->IsUndefined(i_isolate));
1416 i::FunctionTemplateInfo::SetPrototypeProviderTemplate(i_isolate, info,
1417 result);
1418}
1419
1420static void EnsureNotInstantiated(i::Handle<i::FunctionTemplateInfo> info,
1421 const char* func) {
1422 Utils::ApiCheck(!info->instantiated(), func,
1423 "FunctionTemplate already instantiated");
1424}
1425
1426
1427void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) {
1428 auto info = Utils::OpenHandle(this);
1429 EnsureNotInstantiated(info, "v8::FunctionTemplate::Inherit");
1430 i::Isolate* i_isolate = info->GetIsolate();
1431 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1432 CHECK(info->GetPrototypeProviderTemplate()->IsUndefined(i_isolate));
1433 i::FunctionTemplateInfo::SetParentTemplate(i_isolate, info,
1434 Utils::OpenHandle(*value));
1435}
1436
1437static Local<FunctionTemplate> FunctionTemplateNew(
1438 i::Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
1439 v8::Local<Signature> signature, int length, bool do_not_cache,
1440 v8::Local<Private> cached_property_name = v8::Local<Private>(),
1441 SideEffectType side_effect_type = SideEffectType::kHasSideEffect) {
1442 i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
1443 i::FUNCTION_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
1444 i::Handle<i::FunctionTemplateInfo> obj =
1445 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
1446 InitializeFunctionTemplate(obj);
1447 obj->set_do_not_cache(do_not_cache);
1448 int next_serial_number = i::FunctionTemplateInfo::kInvalidSerialNumber;
1449 if (!do_not_cache) {
1450 next_serial_number = isolate->heap()->GetNextTemplateSerialNumber();
1451 }
1452 obj->set_serial_number(i::Smi::FromInt(next_serial_number));
1453 if (callback != nullptr) {
1454 Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type);
1455 }
1456 obj->set_length(length);
1457 obj->set_undetectable(false);
1458 obj->set_needs_access_check(false);
1459 obj->set_accept_any_receiver(true);
1460 if (!signature.IsEmpty()) {
1461 obj->set_signature(*Utils::OpenHandle(*signature));
1462 }
1463 obj->set_cached_property_name(
1464 cached_property_name.IsEmpty()
1465 ? i::ReadOnlyRoots(isolate).the_hole_value()
1466 : *Utils::OpenHandle(*cached_property_name));
1467 return Utils::ToLocal(obj);
1468}
1469
1470Local<FunctionTemplate> FunctionTemplate::New(
1471 Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
1472 v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
1473 SideEffectType side_effect_type) {
1474 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1475 // Changes to the environment cannot be captured in the snapshot. Expect no
1476 // function templates when the isolate is created for serialization.
1477 LOG_API(i_isolate, FunctionTemplate, New);
1478 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1479 auto templ = FunctionTemplateNew(i_isolate, callback, data, signature, length,
1480 false, Local<Private>(), side_effect_type);
1481 if (behavior == ConstructorBehavior::kThrow) templ->RemovePrototype();
1482 return templ;
1483}
1484
1485MaybeLocal<FunctionTemplate> FunctionTemplate::FromSnapshot(Isolate* isolate,
1486 size_t index) {
1487 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1488 i::FixedArray serialized_objects = i_isolate->heap()->serialized_objects();
1489 int int_index = static_cast<int>(index);
1490 if (int_index < serialized_objects->length()) {
1491 i::Object info = serialized_objects->get(int_index);
1492 if (info->IsFunctionTemplateInfo()) {
1493 return Utils::ToLocal(i::Handle<i::FunctionTemplateInfo>(
1494 i::FunctionTemplateInfo::cast(info), i_isolate));
1495 }
1496 }
1497 return Local<FunctionTemplate>();
1498}
1499
1500Local<FunctionTemplate> FunctionTemplate::NewWithCache(
1501 Isolate* isolate, FunctionCallback callback, Local<Private> cache_property,
1502 Local<Value> data, Local<Signature> signature, int length,
1503 SideEffectType side_effect_type) {
1504 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1505 LOG_API(i_isolate, FunctionTemplate, NewWithCache);
1506 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
1507 return FunctionTemplateNew(i_isolate, callback, data, signature, length,
1508 false, cache_property, side_effect_type);
1509}
1510
1511Local<Signature> Signature::New(Isolate* isolate,
1512 Local<FunctionTemplate> receiver) {
1513 return Utils::SignatureToLocal(Utils::OpenHandle(*receiver));
1514}
1515
1516
1517Local<AccessorSignature> AccessorSignature::New(
1518 Isolate* isolate, Local<FunctionTemplate> receiver) {
1519 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
1520}
1521
1522#define SET_FIELD_WRAPPED(isolate, obj, setter, cdata) \
1523 do { \
1524 i::Handle<i::Object> foreign = FromCData(isolate, cdata); \
1525 (obj)->setter(*foreign); \
1526 } while (false)
1527
1528void FunctionTemplate::SetCallHandler(FunctionCallback callback,
1529 v8::Local<Value> data,
1530 SideEffectType side_effect_type) {
1531 auto info = Utils::OpenHandle(this);
1532 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler");
1533 i::Isolate* isolate = info->GetIsolate();
1534 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1535 i::HandleScope scope(isolate);
1536 i::Handle<i::CallHandlerInfo> obj = isolate->factory()->NewCallHandlerInfo(
1537 side_effect_type == SideEffectType::kHasNoSideEffect);
1538 SET_FIELD_WRAPPED(isolate, obj, set_callback, callback);
1539 SET_FIELD_WRAPPED(isolate, obj, set_js_callback, obj->redirected_callback());
1540 if (data.IsEmpty()) {
1541 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1542 }
1543 obj->set_data(*Utils::OpenHandle(*data));
1544 info->set_call_code(*obj);
1545}
1546
1547
1548namespace {
1549
1550template <typename Getter, typename Setter>
1551i::Handle<i::AccessorInfo> MakeAccessorInfo(
1552 i::Isolate* isolate, v8::Local<Name> name, Getter getter, Setter setter,
1553 v8::Local<Value> data, v8::AccessControl settings,
1554 v8::Local<AccessorSignature> signature, bool is_special_data_property,
1555 bool replace_on_access) {
1556 i::Handle<i::AccessorInfo> obj = isolate->factory()->NewAccessorInfo();
1557 SET_FIELD_WRAPPED(isolate, obj, set_getter, getter);
1558 DCHECK_IMPLIES(replace_on_access,
1559 is_special_data_property && setter == nullptr);
1560 if (is_special_data_property && setter == nullptr) {
1561 setter = reinterpret_cast<Setter>(&i::Accessors::ReconfigureToDataProperty);
1562 }
1563 SET_FIELD_WRAPPED(isolate, obj, set_setter, setter);
1564 i::Address redirected = obj->redirected_getter();
1565 if (redirected != i::kNullAddress) {
1566 SET_FIELD_WRAPPED(isolate, obj, set_js_getter, redirected);
1567 }
1568 if (data.IsEmpty()) {
1569 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1570 }
1571 obj->set_data(*Utils::OpenHandle(*data));
1572 obj->set_is_special_data_property(is_special_data_property);
1573 obj->set_replace_on_access(replace_on_access);
1574 i::Handle<i::Name> accessor_name = Utils::OpenHandle(*name);
1575 if (!accessor_name->IsUniqueName()) {
1576 accessor_name = isolate->factory()->InternalizeString(
1577 i::Handle<i::String>::cast(accessor_name));
1578 }
1579 obj->set_name(*accessor_name);
1580 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
1581 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
1582 obj->set_initial_property_attributes(i::NONE);
1583 if (!signature.IsEmpty()) {
1584 obj->set_expected_receiver_type(*Utils::OpenHandle(*signature));
1585 }
1586 return obj;
1587}
1588
1589} // namespace
1590
1591Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
1592 i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
1593 if (!Utils::ApiCheck(!handle.is_null(),
1594 "v8::FunctionTemplate::InstanceTemplate()",
1595 "Reading from empty handle")) {
1596 return Local<ObjectTemplate>();
1597 }
1598 i::Isolate* isolate = handle->GetIsolate();
1599 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1600 if (handle->GetInstanceTemplate()->IsUndefined(isolate)) {
1601 Local<ObjectTemplate> templ =
1602 ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
1603 i::FunctionTemplateInfo::SetInstanceTemplate(isolate, handle,
1604 Utils::OpenHandle(*templ));
1605 }
1606 i::Handle<i::ObjectTemplateInfo> result(
1607 i::ObjectTemplateInfo::cast(handle->GetInstanceTemplate()), isolate);
1608 return Utils::ToLocal(result);
1609}
1610
1611
1612void FunctionTemplate::SetLength(int length) {
1613 auto info = Utils::OpenHandle(this);
1614 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetLength");
1615 auto isolate = info->GetIsolate();
1616 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1617 info->set_length(length);
1618}
1619
1620
1621void FunctionTemplate::SetClassName(Local<String> name) {
1622 auto info = Utils::OpenHandle(this);
1623 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetClassName");
1624 auto isolate = info->GetIsolate();
1625 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1626 info->set_class_name(*Utils::OpenHandle(*name));
1627}
1628
1629
1630void FunctionTemplate::SetAcceptAnyReceiver(bool value) {
1631 auto info = Utils::OpenHandle(this);
1632 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetAcceptAnyReceiver");
1633 auto isolate = info->GetIsolate();
1634 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1635 info->set_accept_any_receiver(value);
1636}
1637
1638
1639void FunctionTemplate::SetHiddenPrototype(bool value) {
1640 auto info = Utils::OpenHandle(this);
1641 EnsureNotInstantiated(info, "v8::FunctionTemplate::SetHiddenPrototype");
1642 auto isolate = info->GetIsolate();
1643 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1644 info->set_hidden_prototype(value);
1645}
1646
1647
1648void FunctionTemplate::ReadOnlyPrototype() {
1649 auto info = Utils::OpenHandle(this);
1650 EnsureNotInstantiated(info, "v8::FunctionTemplate::ReadOnlyPrototype");
1651 auto isolate = info->GetIsolate();
1652 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1653 info->set_read_only_prototype(true);
1654}
1655
1656
1657void FunctionTemplate::RemovePrototype() {
1658 auto info = Utils::OpenHandle(this);
1659 EnsureNotInstantiated(info, "v8::FunctionTemplate::RemovePrototype");
1660 auto isolate = info->GetIsolate();
1661 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1662 info->set_remove_prototype(true);
1663}
1664
1665
1666// --- O b j e c t T e m p l a t e ---
1667
1668
1669Local<ObjectTemplate> ObjectTemplate::New(
1670 Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
1671 return New(reinterpret_cast<i::Isolate*>(isolate), constructor);
1672}
1673
1674
1675static Local<ObjectTemplate> ObjectTemplateNew(
1676 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor,
1677 bool do_not_cache) {
1678 LOG_API(isolate, ObjectTemplate, New);
1679 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1680 i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
1681 i::OBJECT_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
1682 i::Handle<i::ObjectTemplateInfo> obj =
1683 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1684 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
1685 int next_serial_number = 0;
1686 if (!do_not_cache) {
1687 next_serial_number = isolate->heap()->GetNextTemplateSerialNumber();
1688 }
1689 obj->set_serial_number(i::Smi::FromInt(next_serial_number));
1690 if (!constructor.IsEmpty())
1691 obj->set_constructor(*Utils::OpenHandle(*constructor));
1692 obj->set_data(i::Smi::kZero);
1693 return Utils::ToLocal(obj);
1694}
1695
1696Local<ObjectTemplate> ObjectTemplate::New(
1697 i::Isolate* isolate, v8::Local<FunctionTemplate> constructor) {
1698 return ObjectTemplateNew(isolate, constructor, false);
1699}
1700
1701MaybeLocal<ObjectTemplate> ObjectTemplate::FromSnapshot(Isolate* isolate,
1702 size_t index) {
1703 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
1704 i::FixedArray serialized_objects = i_isolate->heap()->serialized_objects();
1705 int int_index = static_cast<int>(index);
1706 if (int_index < serialized_objects->length()) {
1707 i::Object info = serialized_objects->get(int_index);
1708 if (info->IsObjectTemplateInfo()) {
1709 return Utils::ToLocal(i::Handle<i::ObjectTemplateInfo>(
1710 i::ObjectTemplateInfo::cast(info), i_isolate));
1711 }
1712 }
1713 return Local<ObjectTemplate>();
1714}
1715
1716// Ensure that the object template has a constructor. If no
1717// constructor is available we create one.
1718static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
1719 i::Isolate* isolate,
1720 ObjectTemplate* object_template) {
1721 i::Object obj = Utils::OpenHandle(object_template)->constructor();
1722 if (!obj->IsUndefined(isolate)) {
1723 i::FunctionTemplateInfo info = i::FunctionTemplateInfo::cast(obj);
1724 return i::Handle<i::FunctionTemplateInfo>(info, isolate);
1725 }
1726 Local<FunctionTemplate> templ =
1727 FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate));
1728 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1729 i::FunctionTemplateInfo::SetInstanceTemplate(
1730 isolate, constructor, Utils::OpenHandle(object_template));
1731 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1732 return constructor;
1733}
1734
1735template <typename Getter, typename Setter, typename Data, typename Template>
1736static void TemplateSetAccessor(
1737 Template* template_obj, v8::Local<Name> name, Getter getter, Setter setter,
1738 Data data, AccessControl settings, PropertyAttribute attribute,
1739 v8::Local<AccessorSignature> signature, bool is_special_data_property,
1740 bool replace_on_access, SideEffectType getter_side_effect_type,
1741 SideEffectType setter_side_effect_type) {
1742 auto info = Utils::OpenHandle(template_obj);
1743 auto isolate = info->GetIsolate();
1744 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1745 i::HandleScope scope(isolate);
1746 i::Handle<i::AccessorInfo> accessor_info =
1747 MakeAccessorInfo(isolate, name, getter, setter, data, settings, signature,
1748 is_special_data_property, replace_on_access);
1749 accessor_info->set_initial_property_attributes(
1750 static_cast<i::PropertyAttributes>(attribute));
1751 accessor_info->set_getter_side_effect_type(getter_side_effect_type);
1752 accessor_info->set_setter_side_effect_type(setter_side_effect_type);
1753 i::ApiNatives::AddNativeDataProperty(isolate, info, accessor_info);
1754}
1755
1756void Template::SetNativeDataProperty(
1757 v8::Local<String> name, AccessorGetterCallback getter,
1758 AccessorSetterCallback setter, v8::Local<Value> data,
1759 PropertyAttribute attribute, v8::Local<AccessorSignature> signature,
1760 AccessControl settings, SideEffectType getter_side_effect_type,
1761 SideEffectType setter_side_effect_type) {
1762 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1763 signature, true, false, getter_side_effect_type,
1764 setter_side_effect_type);
1765}
1766
1767void Template::SetNativeDataProperty(
1768 v8::Local<Name> name, AccessorNameGetterCallback getter,
1769 AccessorNameSetterCallback setter, v8::Local<Value> data,
1770 PropertyAttribute attribute, v8::Local<AccessorSignature> signature,
1771 AccessControl settings, SideEffectType getter_side_effect_type,
1772 SideEffectType setter_side_effect_type) {
1773 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1774 signature, true, false, getter_side_effect_type,
1775 setter_side_effect_type);
1776}
1777
1778void Template::SetLazyDataProperty(v8::Local<Name> name,
1779 AccessorNameGetterCallback getter,
1780 v8::Local<Value> data,
1781 PropertyAttribute attribute,
1782 SideEffectType getter_side_effect_type,
1783 SideEffectType setter_side_effect_type) {
1784 TemplateSetAccessor(this, name, getter,
1785 static_cast<AccessorNameSetterCallback>(nullptr), data,
1786 DEFAULT, attribute, Local<AccessorSignature>(), true,
1787 true, getter_side_effect_type, setter_side_effect_type);
1788}
1789
1790void Template::SetIntrinsicDataProperty(Local<Name> name, Intrinsic intrinsic,
1791 PropertyAttribute attribute) {
1792 auto templ = Utils::OpenHandle(this);
1793 i::Isolate* isolate = templ->GetIsolate();
1794 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1795 i::HandleScope scope(isolate);
1796 i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
1797 intrinsic,
1798 static_cast<i::PropertyAttributes>(attribute));
1799}
1800
1801void ObjectTemplate::SetAccessor(v8::Local<String> name,
1802 AccessorGetterCallback getter,
1803 AccessorSetterCallback setter,
1804 v8::Local<Value> data, AccessControl settings,
1805 PropertyAttribute attribute,
1806 v8::Local<AccessorSignature> signature,
1807 SideEffectType getter_side_effect_type,
1808 SideEffectType setter_side_effect_type) {
1809 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1810 signature, i::FLAG_disable_old_api_accessors, false,
1811 getter_side_effect_type, setter_side_effect_type);
1812}
1813
1814void ObjectTemplate::SetAccessor(v8::Local<Name> name,
1815 AccessorNameGetterCallback getter,
1816 AccessorNameSetterCallback setter,
1817 v8::Local<Value> data, AccessControl settings,
1818 PropertyAttribute attribute,
1819 v8::Local<AccessorSignature> signature,
1820 SideEffectType getter_side_effect_type,
1821 SideEffectType setter_side_effect_type) {
1822 TemplateSetAccessor(this, name, getter, setter, data, settings, attribute,
1823 signature, i::FLAG_disable_old_api_accessors, false,
1824 getter_side_effect_type, setter_side_effect_type);
1825}
1826
1827template <typename Getter, typename Setter, typename Query, typename Descriptor,
1828 typename Deleter, typename Enumerator, typename Definer>
1829static i::Handle<i::InterceptorInfo> CreateInterceptorInfo(
1830 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1831 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1832 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1833 auto obj = i::Handle<i::InterceptorInfo>::cast(isolate->factory()->NewStruct(
1834 i::INTERCEPTOR_INFO_TYPE, i::AllocationType::kOld));
1835 obj->set_flags(0);
1836
1837 if (getter != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_getter, getter);
1838 if (setter != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_setter, setter);
1839 if (query != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_query, query);
1840 if (descriptor != nullptr)
1841 SET_FIELD_WRAPPED(isolate, obj, set_descriptor, descriptor);
1842 if (remover != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_deleter, remover);
1843 if (enumerator != nullptr)
1844 SET_FIELD_WRAPPED(isolate, obj, set_enumerator, enumerator);
1845 if (definer != nullptr) SET_FIELD_WRAPPED(isolate, obj, set_definer, definer);
1846 obj->set_can_intercept_symbols(
1847 !(static_cast<int>(flags) &
1848 static_cast<int>(PropertyHandlerFlags::kOnlyInterceptStrings)));
1849 obj->set_all_can_read(static_cast<int>(flags) &
1850 static_cast<int>(PropertyHandlerFlags::kAllCanRead));
1851 obj->set_non_masking(static_cast<int>(flags) &
1852 static_cast<int>(PropertyHandlerFlags::kNonMasking));
1853 obj->set_has_no_side_effect(
1854 static_cast<int>(flags) &
1855 static_cast<int>(PropertyHandlerFlags::kHasNoSideEffect));
1856
1857 if (data.IsEmpty()) {
1858 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1859 }
1860 obj->set_data(*Utils::OpenHandle(*data));
1861 return obj;
1862}
1863
1864template <typename Getter, typename Setter, typename Query, typename Descriptor,
1865 typename Deleter, typename Enumerator, typename Definer>
1866static i::Handle<i::InterceptorInfo> CreateNamedInterceptorInfo(
1867 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1868 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1869 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1870 auto interceptor =
1871 CreateInterceptorInfo(isolate, getter, setter, query, descriptor, remover,
1872 enumerator, definer, data, flags);
1873 interceptor->set_is_named(true);
1874 return interceptor;
1875}
1876
1877template <typename Getter, typename Setter, typename Query, typename Descriptor,
1878 typename Deleter, typename Enumerator, typename Definer>
1879static i::Handle<i::InterceptorInfo> CreateIndexedInterceptorInfo(
1880 i::Isolate* isolate, Getter getter, Setter setter, Query query,
1881 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1882 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1883 auto interceptor =
1884 CreateInterceptorInfo(isolate, getter, setter, query, descriptor, remover,
1885 enumerator, definer, data, flags);
1886 interceptor->set_is_named(false);
1887 return interceptor;
1888}
1889
1890template <typename Getter, typename Setter, typename Query, typename Descriptor,
1891 typename Deleter, typename Enumerator, typename Definer>
1892static void ObjectTemplateSetNamedPropertyHandler(
1893 ObjectTemplate* templ, Getter getter, Setter setter, Query query,
1894 Descriptor descriptor, Deleter remover, Enumerator enumerator,
1895 Definer definer, Local<Value> data, PropertyHandlerFlags flags) {
1896 i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate();
1897 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1898 i::HandleScope scope(isolate);
1899 auto cons = EnsureConstructor(isolate, templ);
1900 EnsureNotInstantiated(cons, "ObjectTemplateSetNamedPropertyHandler");
1901 auto obj =
1902 CreateNamedInterceptorInfo(isolate, getter, setter, query, descriptor,
1903 remover, enumerator, definer, data, flags);
1904 i::FunctionTemplateInfo::SetNamedPropertyHandler(isolate, cons, obj);
1905}
1906
1907void ObjectTemplate::SetHandler(
1908 const NamedPropertyHandlerConfiguration& config) {
1909 ObjectTemplateSetNamedPropertyHandler(
1910 this, config.getter, config.setter, config.query, config.descriptor,
1911 config.deleter, config.enumerator, config.definer, config.data,
1912 config.flags);
1913}
1914
1915
1916void ObjectTemplate::MarkAsUndetectable() {
1917 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1918 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1919 i::HandleScope scope(isolate);
1920 auto cons = EnsureConstructor(isolate, this);
1921 EnsureNotInstantiated(cons, "v8::ObjectTemplate::MarkAsUndetectable");
1922 cons->set_undetectable(true);
1923}
1924
1925
1926void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback,
1927 Local<Value> data) {
1928 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1929 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1930 i::HandleScope scope(isolate);
1931 auto cons = EnsureConstructor(isolate, this);
1932 EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallback");
1933
1934 i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct(
1935 i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld);
1936 i::Handle<i::AccessCheckInfo> info =
1937 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1938
1939 SET_FIELD_WRAPPED(isolate, info, set_callback, callback);
1940 info->set_named_interceptor(i::Object());
1941 info->set_indexed_interceptor(i::Object());
1942
1943 if (data.IsEmpty()) {
1944 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1945 }
1946 info->set_data(*Utils::OpenHandle(*data));
1947
1948 i::FunctionTemplateInfo::SetAccessCheckInfo(isolate, cons, info);
1949 cons->set_needs_access_check(true);
1950}
1951
1952void ObjectTemplate::SetAccessCheckCallbackAndHandler(
1953 AccessCheckCallback callback,
1954 const NamedPropertyHandlerConfiguration& named_handler,
1955 const IndexedPropertyHandlerConfiguration& indexed_handler,
1956 Local<Value> data) {
1957 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1958 ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
1959 i::HandleScope scope(isolate);
1960 auto cons = EnsureConstructor(isolate, this);
1961 EnsureNotInstantiated(
1962 cons, "v8::ObjectTemplate::SetAccessCheckCallbackWithHandler");
1963
1964 i::Handle<i::Struct> struct_info =