/
isolate.h
2246 lines (1819 loc) Β· 82.5 KB
/
isolate.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_EXECUTION_ISOLATE_H_
#define V8_EXECUTION_ISOLATE_H_
#include <atomic>
#include <cstddef>
#include <functional>
#include <memory>
#include <queue>
#include <unordered_map>
#include <vector>
#include "include/v8-inspector.h"
#include "include/v8-internal.h"
#include "include/v8-metrics.h"
#include "include/v8.h"
#include "src/base/macros.h"
#include "src/base/platform/mutex.h"
#include "src/builtins/builtins.h"
#include "src/common/globals.h"
#include "src/debug/interface-types.h"
#include "src/execution/execution.h"
#include "src/execution/external-pointer-table.h"
#include "src/execution/futex-emulation.h"
#include "src/execution/isolate-data.h"
#include "src/execution/messages.h"
#include "src/execution/shared-mutex-guard-if-off-thread.h"
#include "src/execution/stack-guard.h"
#include "src/handles/handles.h"
#include "src/heap/factory.h"
#include "src/heap/heap.h"
#include "src/heap/read-only-heap.h"
#include "src/init/isolate-allocator.h"
#include "src/objects/code.h"
#include "src/objects/contexts.h"
#include "src/objects/debug-objects.h"
#include "src/runtime/runtime.h"
#include "src/strings/unicode.h"
#include "src/utils/allocation.h"
#ifdef V8_INTL_SUPPORT
#include "unicode/uversion.h" // Define U_ICU_NAMESPACE.
namespace U_ICU_NAMESPACE {
class UMemory;
} // namespace U_ICU_NAMESPACE
#endif // V8_INTL_SUPPORT
namespace v8 {
namespace base {
class RandomNumberGenerator;
} // namespace base
namespace debug {
class ConsoleDelegate;
class AsyncEventDelegate;
} // namespace debug
namespace internal {
namespace heap {
class HeapTester;
} // namespace heap
class AddressToIndexHashMap;
class AstStringConstants;
class Bootstrapper;
class BuiltinsConstantsTableBuilder;
class CancelableTaskManager;
class CodeEventDispatcher;
class CodeTracer;
class CommonFrame;
class CompilationCache;
class CompilationStatistics;
class CompilerDispatcher;
class Counters;
class Debug;
class Deoptimizer;
class DescriptorLookupCache;
class EmbeddedFileWriterInterface;
class EternalHandles;
class HandleScopeImplementer;
class HeapObjectToIndexHashMap;
class HeapProfiler;
class InnerPointerToCodeCache;
class LocalIsolate;
class Logger;
class MaterializedObjectStore;
class Microtask;
class MicrotaskQueue;
class OptimizingCompileDispatcher;
class PersistentHandles;
class PersistentHandlesList;
class ReadOnlyArtifacts;
class RegExpStack;
class RootVisitor;
class RuntimeProfiler;
class SetupIsolateDelegate;
class Simulator;
class SnapshotData;
class StringTable;
class StubCache;
class ThreadManager;
class ThreadState;
class ThreadVisitor; // Defined in v8threads.h
class TracingCpuProfilerImpl;
class UnicodeCache;
struct ManagedPtrDestructor;
template <StateTag Tag>
class VMState;
namespace interpreter {
class Interpreter;
} // namespace interpreter
namespace compiler {
class NodeObserver;
class PerIsolateCompilerCache;
} // namespace compiler
namespace wasm {
class WasmEngine;
} // namespace wasm
namespace win64_unwindinfo {
class BuiltinUnwindInfo;
} // namespace win64_unwindinfo
namespace metrics {
class Recorder;
} // namespace metrics
#define RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate) \
do { \
Isolate* __isolate__ = (isolate); \
DCHECK(!__isolate__->has_pending_exception()); \
if (__isolate__->has_scheduled_exception()) { \
return __isolate__->PromoteScheduledException(); \
} \
} while (false)
// Macros for MaybeHandle.
#define RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, value) \
do { \
Isolate* __isolate__ = (isolate); \
DCHECK(!__isolate__->has_pending_exception()); \
if (__isolate__->has_scheduled_exception()) { \
__isolate__->PromoteScheduledException(); \
return value; \
} \
} while (false)
#define RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, T) \
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, MaybeHandle<T>())
#define ASSIGN_RETURN_ON_SCHEDULED_EXCEPTION_VALUE(isolate, dst, call, value) \
do { \
Isolate* __isolate__ = (isolate); \
if (!(call).ToLocal(&dst)) { \
DCHECK(__isolate__->has_scheduled_exception()); \
__isolate__->PromoteScheduledException(); \
return value; \
} \
} while (false)
#define RETURN_ON_SCHEDULED_EXCEPTION_VALUE(isolate, call, value) \
do { \
Isolate* __isolate__ = (isolate); \
if ((call).IsNothing()) { \
DCHECK(__isolate__->has_scheduled_exception()); \
__isolate__->PromoteScheduledException(); \
return value; \
} \
} while (false)
/**
* RETURN_RESULT_OR_FAILURE is used in functions with return type Object (such
* as "RUNTIME_FUNCTION(...) {...}" or "BUILTIN(...) {...}" ) to return either
* the contents of a MaybeHandle<X>, or the "exception" sentinel value.
* Example usage:
*
* RUNTIME_FUNCTION(Runtime_Func) {
* ...
* RETURN_RESULT_OR_FAILURE(
* isolate,
* FunctionWithReturnTypeMaybeHandleX(...));
* }
*
* If inside a function with return type MaybeHandle<X> use RETURN_ON_EXCEPTION
* instead.
* If inside a function with return type Handle<X>, or Maybe<X> use
* RETURN_ON_EXCEPTION_VALUE instead.
*/
#define RETURN_RESULT_OR_FAILURE(isolate, call) \
do { \
Handle<Object> __result__; \
Isolate* __isolate__ = (isolate); \
if (!(call).ToHandle(&__result__)) { \
DCHECK(__isolate__->has_pending_exception()); \
return ReadOnlyRoots(__isolate__).exception(); \
} \
DCHECK(!__isolate__->has_pending_exception()); \
return *__result__; \
} while (false)
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value) \
do { \
if (!(call).ToHandle(&dst)) { \
DCHECK((isolate)->has_pending_exception()); \
return value; \
} \
} while (false)
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call) \
do { \
auto* __isolate__ = (isolate); \
ASSIGN_RETURN_ON_EXCEPTION_VALUE(__isolate__, dst, call, \
ReadOnlyRoots(__isolate__).exception()); \
} while (false)
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T) \
ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, MaybeHandle<T>())
#define THROW_NEW_ERROR(isolate, call, T) \
do { \
auto* __isolate__ = (isolate); \
return __isolate__->template Throw<T>(__isolate__->factory()->call); \
} while (false)
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call) \
do { \
auto* __isolate__ = (isolate); \
return __isolate__->Throw(*__isolate__->factory()->call); \
} while (false)
#define THROW_NEW_ERROR_RETURN_VALUE(isolate, call, value) \
do { \
auto* __isolate__ = (isolate); \
__isolate__->Throw(*__isolate__->factory()->call); \
return value; \
} while (false)
/**
* RETURN_ON_EXCEPTION_VALUE conditionally returns the given value when the
* given MaybeHandle is empty. It is typically used in functions with return
* type Maybe<X> or Handle<X>. Example usage:
*
* Handle<X> Func() {
* ...
* RETURN_ON_EXCEPTION_VALUE(
* isolate,
* FunctionWithReturnTypeMaybeHandleX(...),
* Handle<X>());
* // code to handle non exception
* ...
* }
*
* Maybe<bool> Func() {
* ..
* RETURN_ON_EXCEPTION_VALUE(
* isolate,
* FunctionWithReturnTypeMaybeHandleX(...),
* Nothing<bool>);
* // code to handle non exception
* return Just(true);
* }
*
* If inside a function with return type MaybeHandle<X>, use RETURN_ON_EXCEPTION
* instead.
* If inside a function with return type Object, use
* RETURN_FAILURE_ON_EXCEPTION instead.
*/
#define RETURN_ON_EXCEPTION_VALUE(isolate, call, value) \
do { \
if ((call).is_null()) { \
DCHECK((isolate)->has_pending_exception()); \
return value; \
} \
} while (false)
/**
* RETURN_FAILURE_ON_EXCEPTION conditionally returns the "exception" sentinel if
* the given MaybeHandle is empty; so it can only be used in functions with
* return type Object, such as RUNTIME_FUNCTION(...) {...} or BUILTIN(...)
* {...}. Example usage:
*
* RUNTIME_FUNCTION(Runtime_Func) {
* ...
* RETURN_FAILURE_ON_EXCEPTION(
* isolate,
* FunctionWithReturnTypeMaybeHandleX(...));
* // code to handle non exception
* ...
* }
*
* If inside a function with return type MaybeHandle<X>, use RETURN_ON_EXCEPTION
* instead.
* If inside a function with return type Maybe<X> or Handle<X>, use
* RETURN_ON_EXCEPTION_VALUE instead.
*/
#define RETURN_FAILURE_ON_EXCEPTION(isolate, call) \
do { \
Isolate* __isolate__ = (isolate); \
RETURN_ON_EXCEPTION_VALUE(__isolate__, call, \
ReadOnlyRoots(__isolate__).exception()); \
} while (false);
/**
* RETURN_ON_EXCEPTION conditionally returns an empty MaybeHandle<T> if the
* given MaybeHandle is empty. Use it to return immediately from a function with
* return type MaybeHandle when an exception was thrown. Example usage:
*
* MaybeHandle<X> Func() {
* ...
* RETURN_ON_EXCEPTION(
* isolate,
* FunctionWithReturnTypeMaybeHandleY(...),
* X);
* // code to handle non exception
* ...
* }
*
* If inside a function with return type Object, use
* RETURN_FAILURE_ON_EXCEPTION instead.
* If inside a function with return type
* Maybe<X> or Handle<X>, use RETURN_ON_EXCEPTION_VALUE instead.
*/
#define RETURN_ON_EXCEPTION(isolate, call, T) \
RETURN_ON_EXCEPTION_VALUE(isolate, call, MaybeHandle<T>())
#define RETURN_FAILURE(isolate, should_throw, call) \
do { \
if ((should_throw) == kDontThrow) { \
return Just(false); \
} else { \
isolate->Throw(*isolate->factory()->call); \
return Nothing<bool>(); \
} \
} while (false)
#define MAYBE_RETURN(call, value) \
do { \
if ((call).IsNothing()) return value; \
} while (false)
#define MAYBE_RETURN_NULL(call) MAYBE_RETURN(call, MaybeHandle<Object>())
#define MAYBE_ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call) \
do { \
Isolate* __isolate__ = (isolate); \
if (!(call).To(&dst)) { \
DCHECK(__isolate__->has_pending_exception()); \
return ReadOnlyRoots(__isolate__).exception(); \
} \
} while (false)
#define FOR_WITH_HANDLE_SCOPE(isolate, loop_var_type, init, loop_var, \
limit_check, increment, body) \
do { \
loop_var_type init; \
loop_var_type for_with_handle_limit = loop_var; \
Isolate* for_with_handle_isolate = isolate; \
while (limit_check) { \
for_with_handle_limit += 1024; \
HandleScope loop_scope(for_with_handle_isolate); \
for (; limit_check && loop_var < for_with_handle_limit; increment) { \
body \
} \
} \
} while (false)
#define WHILE_WITH_HANDLE_SCOPE(isolate, limit_check, body) \
do { \
Isolate* for_with_handle_isolate = isolate; \
while (limit_check) { \
HandleScope loop_scope(for_with_handle_isolate); \
for (int for_with_handle_it = 0; \
limit_check && for_with_handle_it < 1024; ++for_with_handle_it) { \
body \
} \
} \
} while (false)
#define FIELD_ACCESSOR(type, name) \
inline void set_##name(type v) { name##_ = v; } \
inline type name() const { return name##_; }
// Controls for manual embedded blob lifecycle management, used by tests and
// mksnapshot.
V8_EXPORT_PRIVATE void DisableEmbeddedBlobRefcounting();
V8_EXPORT_PRIVATE void FreeCurrentEmbeddedBlob();
#ifdef DEBUG
#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V) \
V(CommentStatistic, paged_space_comments_statistics, \
CommentStatistic::kMaxComments + 1) \
V(int, code_kind_statistics, kCodeKindCount)
#else
#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
#endif
#define ISOLATE_INIT_ARRAY_LIST(V) \
/* SerializerDeserializer state. */ \
V(int32_t, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize) \
V(int, bad_char_shift_table, kUC16AlphabetSize) \
V(int, good_suffix_shift_table, (kBMMaxShift + 1)) \
V(int, suffix_table, (kBMMaxShift + 1)) \
ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
using DebugObjectCache = std::vector<Handle<HeapObject>>;
#define ISOLATE_INIT_LIST(V) \
/* Assembler state. */ \
V(FatalErrorCallback, exception_behavior, nullptr) \
V(OOMErrorCallback, oom_behavior, nullptr) \
V(LogEventCallback, event_logger, nullptr) \
V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, nullptr) \
V(ModifyCodeGenerationFromStringsCallback, modify_code_gen_callback, \
nullptr) \
V(ModifyCodeGenerationFromStringsCallback2, modify_code_gen_callback2, \
nullptr) \
V(AllowWasmCodeGenerationCallback, allow_wasm_code_gen_callback, nullptr) \
V(ExtensionCallback, wasm_module_callback, &NoExtension) \
V(ExtensionCallback, wasm_instance_callback, &NoExtension) \
V(WasmStreamingCallback, wasm_streaming_callback, nullptr) \
V(WasmLoadSourceMapCallback, wasm_load_source_map_callback, nullptr) \
V(WasmSimdEnabledCallback, wasm_simd_enabled_callback, nullptr) \
V(WasmExceptionsEnabledCallback, wasm_exceptions_enabled_callback, nullptr) \
/* State for Relocatable. */ \
V(Relocatable*, relocatable_top, nullptr) \
V(DebugObjectCache*, string_stream_debug_object_cache, nullptr) \
V(Object, string_stream_current_security_token, Object()) \
V(const intptr_t*, api_external_references, nullptr) \
V(AddressToIndexHashMap*, external_reference_map, nullptr) \
V(HeapObjectToIndexHashMap*, root_index_map, nullptr) \
V(MicrotaskQueue*, default_microtask_queue, nullptr) \
V(CompilationStatistics*, turbo_statistics, nullptr) \
V(CodeTracer*, code_tracer, nullptr) \
V(uint32_t, per_isolate_assert_data, 0xFFFFFFFFu) \
V(PromiseRejectCallback, promise_reject_callback, nullptr) \
V(const v8::StartupData*, snapshot_blob, nullptr) \
V(int, code_and_metadata_size, 0) \
V(int, bytecode_and_metadata_size, 0) \
V(int, external_script_source_size, 0) \
/* Number of CPU profilers running on the isolate. */ \
V(size_t, num_cpu_profilers, 0) \
/* true if a trace is being formatted through Error.prepareStackTrace. */ \
V(bool, formatting_stack_trace, false) \
/* Perform side effect checks on function call and API callbacks. */ \
V(DebugInfo::ExecutionMode, debug_execution_mode, DebugInfo::kBreakpoints) \
V(debug::TypeProfileMode, type_profile_mode, debug::TypeProfileMode::kNone) \
V(bool, disable_bytecode_flushing, false) \
V(int, last_console_context_id, 0) \
V(v8_inspector::V8Inspector*, inspector, nullptr) \
V(bool, next_v8_call_is_safe_for_termination, false) \
V(bool, only_terminate_in_safe_scope, false) \
V(bool, detailed_source_positions_for_profiling, FLAG_detailed_line_info) \
V(int, embedder_wrapper_type_index, -1) \
V(int, embedder_wrapper_object_index, -1) \
V(compiler::NodeObserver*, node_observer, nullptr)
#define THREAD_LOCAL_TOP_ACCESSOR(type, name) \
inline void set_##name(type v) { thread_local_top()->name##_ = v; } \
inline type name() const { return thread_local_top()->name##_; }
#define THREAD_LOCAL_TOP_ADDRESS(type, name) \
type* name##_address() { return &thread_local_top()->name##_; }
// HiddenFactory exists so Isolate can privately inherit from it without making
// Factory's members available to Isolate directly.
class V8_EXPORT_PRIVATE HiddenFactory : private Factory {};
class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
// These forward declarations are required to make the friend declarations in
// PerIsolateThreadData work on some older versions of gcc.
class ThreadDataTable;
class EntryStackItem;
public:
Isolate(const Isolate&) = delete;
Isolate& operator=(const Isolate&) = delete;
using HandleScopeType = HandleScope;
void* operator new(size_t) = delete;
void operator delete(void*) = delete;
// A thread has a PerIsolateThreadData instance for each isolate that it has
// entered. That instance is allocated when the isolate is initially entered
// and reused on subsequent entries.
class PerIsolateThreadData {
public:
PerIsolateThreadData(Isolate* isolate, ThreadId thread_id)
: isolate_(isolate),
thread_id_(thread_id),
stack_limit_(0),
thread_state_(nullptr)
#if USE_SIMULATOR
,
simulator_(nullptr)
#endif
{
}
~PerIsolateThreadData();
PerIsolateThreadData(const PerIsolateThreadData&) = delete;
PerIsolateThreadData& operator=(const PerIsolateThreadData&) = delete;
Isolate* isolate() const { return isolate_; }
ThreadId thread_id() const { return thread_id_; }
FIELD_ACCESSOR(uintptr_t, stack_limit)
FIELD_ACCESSOR(ThreadState*, thread_state)
#if USE_SIMULATOR
FIELD_ACCESSOR(Simulator*, simulator)
#endif
bool Matches(Isolate* isolate, ThreadId thread_id) const {
return isolate_ == isolate && thread_id_ == thread_id;
}
private:
Isolate* isolate_;
ThreadId thread_id_;
uintptr_t stack_limit_;
ThreadState* thread_state_;
#if USE_SIMULATOR
Simulator* simulator_;
#endif
friend class Isolate;
friend class ThreadDataTable;
friend class EntryStackItem;
};
static void InitializeOncePerProcess();
// Creates Isolate object. Must be used instead of constructing Isolate with
// new operator.
static Isolate* New();
// Deletes Isolate object. Must be used instead of delete operator.
// Destroys the non-default isolates.
// Sets default isolate into "has_been_disposed" state rather then destroying,
// for legacy API reasons.
static void Delete(Isolate* isolate);
void SetUpFromReadOnlyArtifacts(std::shared_ptr<ReadOnlyArtifacts> artifacts,
ReadOnlyHeap* ro_heap);
void set_read_only_heap(ReadOnlyHeap* ro_heap) { read_only_heap_ = ro_heap; }
// Page allocator that must be used for allocating V8 heap pages.
v8::PageAllocator* page_allocator();
// Returns the PerIsolateThreadData for the current thread (or nullptr if one
// is not currently set).
static PerIsolateThreadData* CurrentPerIsolateThreadData() {
return reinterpret_cast<PerIsolateThreadData*>(
base::Thread::GetThreadLocal(per_isolate_thread_data_key_));
}
// Returns the isolate inside which the current thread is running or nullptr.
V8_INLINE static Isolate* TryGetCurrent() {
DCHECK_EQ(true, isolate_key_created_.load(std::memory_order_relaxed));
return reinterpret_cast<Isolate*>(
base::Thread::GetExistingThreadLocal(isolate_key_));
}
// Returns the isolate inside which the current thread is running.
V8_INLINE static Isolate* Current() {
Isolate* isolate = TryGetCurrent();
DCHECK_NOT_NULL(isolate);
return isolate;
}
// Usually called by Init(), but can be called early e.g. to allow
// testing components that require logging but not the whole
// isolate.
//
// Safe to call more than once.
void InitializeLoggingAndCounters();
bool InitializeCounters(); // Returns false if already initialized.
bool InitWithoutSnapshot();
bool InitWithSnapshot(SnapshotData* startup_snapshot_data,
SnapshotData* read_only_snapshot_data, bool can_rehash);
// True if at least one thread Enter'ed this isolate.
bool IsInUse() { return entry_stack_ != nullptr; }
void ReleaseSharedPtrs();
void ClearSerializerData();
bool LogObjectRelocation();
// Initializes the current thread to run this Isolate.
// Not thread-safe. Multiple threads should not Enter/Exit the same isolate
// at the same time, this should be prevented using external locking.
void Enter();
// Exits the current thread. The previosuly entered Isolate is restored
// for the thread.
// Not thread-safe. Multiple threads should not Enter/Exit the same isolate
// at the same time, this should be prevented using external locking.
void Exit();
// Find the PerThread for this particular (isolate, thread) combination.
// If one does not yet exist, allocate a new one.
PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();
// Find the PerThread for this particular (isolate, thread) combination
// If one does not yet exist, return null.
PerIsolateThreadData* FindPerThreadDataForThisThread();
// Find the PerThread for given (isolate, thread) combination
// If one does not yet exist, return null.
PerIsolateThreadData* FindPerThreadDataForThread(ThreadId thread_id);
// Discard the PerThread for this particular (isolate, thread) combination
// If one does not yet exist, no-op.
void DiscardPerThreadDataForThisThread();
// Mutex for serializing access to break control structures.
base::RecursiveMutex* break_access() { return &break_access_; }
// Shared mutex for allowing concurrent read/writes to FeedbackVectors.
base::SharedMutex* feedback_vector_access() {
return &feedback_vector_access_;
}
// Shared mutex for allowing concurrent read/writes to Strings.
base::SharedMutex* string_access() { return &string_access_; }
// Shared mutex for allowing concurrent read/writes to TransitionArrays.
base::SharedMutex* transition_array_access() {
return &transition_array_access_;
}
// Shared mutex for allowing concurrent read/writes to SharedFunctionInfos.
base::SharedMutex* shared_function_info_access() {
return &shared_function_info_access_;
}
// The isolate's string table.
StringTable* string_table() { return string_table_.get(); }
Address get_address_from_id(IsolateAddressId id);
// Access to top context (where the current function object was created).
Context context() { return thread_local_top()->context_; }
inline void set_context(Context context);
Context* context_address() { return &thread_local_top()->context_; }
// Access to current thread id.
inline void set_thread_id(ThreadId id) {
thread_local_top()->thread_id_.store(id, std::memory_order_relaxed);
}
inline ThreadId thread_id() const {
return thread_local_top()->thread_id_.load(std::memory_order_relaxed);
}
// Interface to pending exception.
inline Object pending_exception();
inline void set_pending_exception(Object exception_obj);
inline void clear_pending_exception();
bool IsWasmSimdEnabled(Handle<Context> context);
bool AreWasmExceptionsEnabled(Handle<Context> context);
THREAD_LOCAL_TOP_ADDRESS(Object, pending_exception)
inline bool has_pending_exception();
THREAD_LOCAL_TOP_ADDRESS(Context, pending_handler_context)
THREAD_LOCAL_TOP_ADDRESS(Address, pending_handler_entrypoint)
THREAD_LOCAL_TOP_ADDRESS(Address, pending_handler_constant_pool)
THREAD_LOCAL_TOP_ADDRESS(Address, pending_handler_fp)
THREAD_LOCAL_TOP_ADDRESS(Address, pending_handler_sp)
THREAD_LOCAL_TOP_ACCESSOR(bool, external_caught_exception)
v8::TryCatch* try_catch_handler() {
return thread_local_top()->try_catch_handler_;
}
bool* external_caught_exception_address() {
return &thread_local_top()->external_caught_exception_;
}
THREAD_LOCAL_TOP_ADDRESS(Object, scheduled_exception)
inline void clear_pending_message();
Address pending_message_obj_address() {
return reinterpret_cast<Address>(&thread_local_top()->pending_message_obj_);
}
inline Object scheduled_exception();
inline bool has_scheduled_exception();
inline void clear_scheduled_exception();
bool IsJavaScriptHandlerOnTop(Object exception);
bool IsExternalHandlerOnTop(Object exception);
inline bool is_catchable_by_javascript(Object exception);
inline bool is_catchable_by_wasm(Object exception);
// JS execution stack (see frames.h).
static Address c_entry_fp(ThreadLocalTop* thread) {
return thread->c_entry_fp_;
}
static Address handler(ThreadLocalTop* thread) { return thread->handler_; }
Address c_function() { return thread_local_top()->c_function_; }
inline Address* c_entry_fp_address() {
return &thread_local_top()->c_entry_fp_;
}
static uint32_t c_entry_fp_offset() {
return static_cast<uint32_t>(
OFFSET_OF(Isolate, thread_local_top()->c_entry_fp_) -
isolate_root_bias());
}
inline Address* handler_address() { return &thread_local_top()->handler_; }
inline Address* c_function_address() {
return &thread_local_top()->c_function_;
}
#if defined(DEBUG) || defined(VERIFY_HEAP)
// Count the number of active deserializers, so that the heap verifier knows
// whether there is currently an active deserialization happening.
//
// This is needed as the verifier currently doesn't support verifying objects
// which are partially deserialized.
//
// TODO(leszeks): Make the verifier a bit more deserialization compatible.
void RegisterDeserializerStarted() { ++num_active_deserializers_; }
void RegisterDeserializerFinished() {
CHECK_GE(--num_active_deserializers_, 0);
}
bool has_active_deserializer() const {
return num_active_deserializers_.load(std::memory_order_acquire) > 0;
}
#else
void RegisterDeserializerStarted() {}
void RegisterDeserializerFinished() {}
bool has_active_deserializer() const { UNREACHABLE(); }
#endif
// Bottom JS entry.
Address js_entry_sp() { return thread_local_top()->js_entry_sp_; }
inline Address* js_entry_sp_address() {
return &thread_local_top()->js_entry_sp_;
}
std::vector<MemoryRange>* GetCodePages() const;
void SetCodePages(std::vector<MemoryRange>* new_code_pages);
// Returns the global object of the current context. It could be
// a builtin object, or a JS global object.
inline Handle<JSGlobalObject> global_object();
// Returns the global proxy object of the current context.
inline Handle<JSGlobalProxy> global_proxy();
static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
void FreeThreadResources() { thread_local_top()->Free(); }
// This method is called by the api after operations that may throw
// exceptions. If an exception was thrown and not handled by an external
// handler the exception is scheduled to be rethrown when we return to running
// JavaScript code. If an exception is scheduled true is returned.
bool OptionalRescheduleException(bool clear_exception);
// Push and pop a promise and the current try-catch handler.
void PushPromise(Handle<JSObject> promise);
void PopPromise();
// Return the relevant Promise that a throw/rejection pertains to, based
// on the contents of the Promise stack
Handle<Object> GetPromiseOnStackOnThrow();
// Heuristically guess whether a Promise is handled by user catch handler
bool PromiseHasUserDefinedRejectHandler(Handle<JSPromise> promise);
class V8_NODISCARD ExceptionScope {
public:
// Scope currently can only be used for regular exceptions,
// not termination exception.
inline explicit ExceptionScope(Isolate* isolate);
inline ~ExceptionScope();
private:
Isolate* isolate_;
Handle<Object> pending_exception_;
};
void SetCaptureStackTraceForUncaughtExceptions(
bool capture, int frame_limit, StackTrace::StackTraceOptions options);
bool get_capture_stack_trace_for_uncaught_exceptions() const;
void SetAbortOnUncaughtExceptionCallback(
v8::Isolate::AbortOnUncaughtExceptionCallback callback);
enum PrintStackMode { kPrintStackConcise, kPrintStackVerbose };
void PrintCurrentStackTrace(FILE* out);
void PrintStack(StringStream* accumulator,
PrintStackMode mode = kPrintStackVerbose);
void PrintStack(FILE* out, PrintStackMode mode = kPrintStackVerbose);
Handle<String> StackTraceString();
// Stores a stack trace in a stack-allocated temporary buffer which will
// end up in the minidump for debugging purposes.
V8_NOINLINE void PushStackTraceAndDie(void* ptr1 = nullptr,
void* ptr2 = nullptr,
void* ptr3 = nullptr,
void* ptr4 = nullptr);
Handle<FixedArray> CaptureCurrentStackTrace(
int frame_limit, StackTrace::StackTraceOptions options);
Handle<Object> CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
FrameSkipMode mode,
Handle<Object> caller);
MaybeHandle<JSReceiver> CaptureAndSetDetailedStackTrace(
Handle<JSReceiver> error_object);
MaybeHandle<JSReceiver> CaptureAndSetSimpleStackTrace(
Handle<JSReceiver> error_object, FrameSkipMode mode,
Handle<Object> caller);
Handle<FixedArray> GetDetailedStackTrace(Handle<JSObject> error_object);
Address GetAbstractPC(int* line, int* column);
// Returns if the given context may access the given global object. If
// the result is false, the pending exception is guaranteed to be
// set.
bool MayAccess(Handle<Context> accessing_context, Handle<JSObject> receiver);
void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
void ReportFailedAccessCheck(Handle<JSObject> receiver);
// Exception throwing support. The caller should use the result
// of Throw() as its return value.
Object Throw(Object exception) { return ThrowInternal(exception, nullptr); }
Object ThrowAt(Handle<JSObject> exception, MessageLocation* location);
Object ThrowIllegalOperation();
template <typename T>
V8_WARN_UNUSED_RESULT MaybeHandle<T> Throw(Handle<Object> exception) {
Throw(*exception);
return MaybeHandle<T>();
}
template <typename T>
V8_WARN_UNUSED_RESULT MaybeHandle<T> ThrowAt(Handle<JSObject> exception,
MessageLocation* location) {
ThrowAt(exception, location);
return MaybeHandle<T>();
}
void FatalProcessOutOfHeapMemory(const char* location) {
heap()->FatalProcessOutOfMemory(location);
}
void set_console_delegate(debug::ConsoleDelegate* delegate) {
console_delegate_ = delegate;
}
debug::ConsoleDelegate* console_delegate() { return console_delegate_; }
void set_async_event_delegate(debug::AsyncEventDelegate* delegate) {
async_event_delegate_ = delegate;
PromiseHookStateUpdated();
}
void OnAsyncFunctionStateChanged(Handle<JSPromise> promise,
debug::DebugAsyncActionType);
// Re-throw an exception. This involves no error reporting since error
// reporting was handled when the exception was thrown originally.
Object ReThrow(Object exception);
// Find the correct handler for the current pending exception. This also
// clears and returns the current pending exception.
Object UnwindAndFindHandler();
// Tries to predict whether an exception will be caught. Note that this can
// only produce an estimate, because it is undecidable whether a finally
// clause will consume or re-throw an exception.
enum CatchType {
NOT_CAUGHT,
CAUGHT_BY_JAVASCRIPT,
CAUGHT_BY_EXTERNAL,
CAUGHT_BY_DESUGARING,
CAUGHT_BY_PROMISE,
CAUGHT_BY_ASYNC_AWAIT
};
CatchType PredictExceptionCatcher();
void ScheduleThrow(Object exception);
// Re-set pending message, script and positions reported to the TryCatch
// back to the TLS for re-use when rethrowing.
void RestorePendingMessageFromTryCatch(v8::TryCatch* handler);
// Un-schedule an exception that was caught by a TryCatch handler.
void CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler);
void ReportPendingMessages();
// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
Object PromoteScheduledException();
// Attempts to compute the current source location, storing the
// result in the target out parameter. The source location is attached to a
// Message object as the location which should be shown to the user. It's
// typically the top-most meaningful location on the stack.
bool ComputeLocation(MessageLocation* target);
bool ComputeLocationFromException(MessageLocation* target,
Handle<Object> exception);
bool ComputeLocationFromStackTrace(MessageLocation* target,
Handle<Object> exception);
Handle<JSMessageObject> CreateMessage(Handle<Object> exception,
MessageLocation* location);
Handle<JSMessageObject> CreateMessageOrAbort(Handle<Object> exception,
MessageLocation* location);
// Out of resource exception helpers.
Object StackOverflow();
Object TerminateExecution();
void CancelTerminateExecution();
void RequestInterrupt(InterruptCallback callback, void* data);
void InvokeApiInterruptCallbacks();
// Administration
void Iterate(RootVisitor* v);
void Iterate(RootVisitor* v, ThreadLocalTop* t);
char* Iterate(RootVisitor* v, char* t);
void IterateThread(ThreadVisitor* v, char* t);
// Returns the current native context.
inline Handle<NativeContext> native_context();
inline NativeContext raw_native_context();
Handle<Context> GetIncumbentContext();
void RegisterTryCatchHandler(v8::TryCatch* that);
void UnregisterTryCatchHandler(v8::TryCatch* that);
char* ArchiveThread(char* to);
char* RestoreThread(char* from);
static const int kUC16AlphabetSize = 256; // See StringSearchBase.
static const int kBMMaxShift = 250; // See StringSearchBase.
// Accessors.
#define GLOBAL_ACCESSOR(type, name, initialvalue) \
inline type name() const { \
DCHECK(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
return name##_; \
} \
inline void set_##name(type value) { \
DCHECK(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
name##_ = value; \
}
ISOLATE_INIT_LIST(GLOBAL_ACCESSOR)
#undef GLOBAL_ACCESSOR
#define GLOBAL_ARRAY_ACCESSOR(type, name, length) \
inline type* name() { \
DCHECK(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
return &(name##_)[0]; \
}
ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)
#undef GLOBAL_ARRAY_ACCESSOR
#define NATIVE_CONTEXT_FIELD_ACCESSOR(index, type, name) \
inline Handle<type> name(); \
inline bool is_##name(type value);
NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSOR)
#undef NATIVE_CONTEXT_FIELD_ACCESSOR
Bootstrapper* bootstrapper() { return bootstrapper_; }
// Use for updating counters on a foreground thread.
Counters* counters() { return async_counters().get(); }
// Use for updating counters on a background thread.
const std::shared_ptr<Counters>& async_counters() {
// Make sure InitializeCounters() has been called.
DCHECK_NOT_NULL(async_counters_.get());
return async_counters_;
}
const std::shared_ptr<metrics::Recorder>& metrics_recorder() {
return metrics_recorder_;
}
RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
CompilationCache* compilation_cache() { return compilation_cache_; }
Logger* logger() {
// Call InitializeLoggingAndCounters() if logging is needed before
// the isolate is fully initialized.
DCHECK_NOT_NULL(logger_);