34 auto names = NameToIndexHashTable::New(isolate, 16);
36 std::optional<DisallowGarbageCollection> no_gc;
38 Allocate(isolate, capacity, &no_gc, allocation);
40 result->set_names_to_context_index(*names);
53 int script_context_index) {
56 int local_count = scope_info->ContextLocalCount();
57 names_table = names_table->EnsureCapacity(isolate, names_table, local_count);
61 if (ignore_duplicates) {
63 if (names_table->FindEntry(isolate, roots, name, hash).is_found()) {
68 script_context_index);
79 DCHECK(script_context->IsScriptContext());
86 int old_capacity = table->capacity();
88 if (old_length == old_capacity) {
90 auto new_table =
New(isolate, new_capacity);
92 new_table->set_names_to_context_index(table->names_to_context_index());
93 CopyElements(isolate, *new_table, 0, *table, 0, old_length);
99 names_table = AddLocalNamesFromContext(isolate, names_table, script_context,
100 ignore_duplicates, old_length);
101 result->set_names_to_context_index(*names_table);
110 int header = scope_info->ContextHeaderLength();
111 for (
int var = 0; var < scope_info->ContextLocalCount(); var++) {
122 if (index == -1)
return false;
126 DCHECK(context->IsScriptContext());
127 int slot_index = context->scope_info()->ContextSlotIndex(name,
result);
128 if (slot_index < 0)
return false;
130 result->slot_index = slot_index;
143 return scope_info()->is_declaration_scope();
148 while (!current->is_declaration_context()) {
149 current = current->previous();
156 while (!current->IsFunctionContext() && !current->IsScriptContext() &&
157 !current->IsModuleContext() && !IsNativeContext(current) &&
158 !current->IsEvalContext()) {
159 current = current->previous();
168 if (IsUndefined(
object))
return JSObject();
169 DCHECK(IsJSContextExtensionObject(
object) ||
170 (IsNativeContext(*
this) && IsJSGlobalObject(
object)));
182 while (!current->IsModuleContext()) {
183 current = current->previous();
194 while (!current->IsScriptContext()) {
195 current = current->previous();
216 isolate, unscopables,
218 isolate->factory()->unscopables_symbol()),
220 if (!IsJSReceiver(*unscopables))
return Just(
true);
241 bool* is_sloppy_function_name) {
242 Isolate* isolate = context->GetIsolate();
245 bool has_seen_debug_evaluate_context =
false;
250 if (is_sloppy_function_name !=
nullptr) {
251 *is_sloppy_function_name =
false;
255 PrintF(
"Context::Lookup(");
262 PrintF(
" - looking in context %p",
263 reinterpret_cast<void*
>(context->ptr()));
264 if (context->IsScriptContext())
PrintF(
" (script context)");
265 if (IsNativeContext(*context))
PrintF(
" (native context)");
266 if (context->IsDebugEvaluateContext())
PrintF(
" (debug context)");
271 DCHECK_IMPLIES(context->IsEvalContext() && context->has_extension(),
272 IsTheHole(context->extension(), isolate));
273 if ((IsNativeContext(*context) || context->IsWithContext() ||
274 context->IsFunctionContext() || context->IsBlockContext()) &&
275 context->has_extension() && !context->extension_receiver().is_null()) {
278 if (IsNativeContext(*context)) {
281 PrintF(
" - trying other script contexts\n");
285 context->native_context()->script_context_table();
287 if (script_contexts->Lookup(name, &
r)) {
289 script_contexts->get(
r.context_index);
291 PrintF(
"=> found property in script context %d: %p\n",
295 *index =
r.slot_index;
296 *variable_mode =
r.mode;
297 *init_flag =
r.init_flag;
308 IsJSContextExtensionObject(*
object)) {
335 DCHECK(!isolate->has_exception());
340 PrintF(
"=> found property in context object %p\n",
341 reinterpret_cast<void*
>(object->ptr()));
348 if (context->IsFunctionContext() || context->IsBlockContext() ||
349 context->IsScriptContext() || context->IsEvalContext() ||
350 context->IsModuleContext() || context->IsCatchContext()) {
356 int slot_index = scope_info->ContextSlotIndex(name, &lookup_result);
358 if (slot_index >= 0) {
364 if (scope_info->IsReplModeScope() &&
365 IsTheHole(context->get(slot_index), isolate)) {
371 PrintF(
"=> found local in context slot %d (mode = %hhu)\n",
372 slot_index,
static_cast<uint8_t
>(lookup_result.
mode));
375 *variable_mode = lookup_result.
mode;
384 if (follow_context_chain && context->IsFunctionContext()) {
385 int function_index = scope_info->FunctionContextSlotIndex(*name);
386 if (function_index >= 0) {
388 PrintF(
"=> found intermediate function in context slot %d\n",
391 *index = function_index;
395 if (is_sloppy_function_name !=
nullptr &&
396 is_sloppy(scope_info->language_mode())) {
397 *is_sloppy_function_name =
true;
404 if (context->IsModuleContext()) {
409 scope_info->ModuleIndex(*name, &mode, &flag, &maybe_assigned_flag);
410 if (cell_index != 0) {
412 PrintF(
"=> found in module imports or exports\n");
415 *variable_mode =
mode;
421 return handle(context->module(), isolate);
424 }
else if (context->IsDebugEvaluateContext()) {
425 has_seen_debug_evaluate_context =
true;
429 if (IsJSReceiver(ext)) {
441 if (IsContext(obj)) {
445 attributes, init_flag, variable_mode);
451 if (IsNativeContext(*context))
break;
459 if (has_seen_debug_evaluate_context &&
460 IsEphemeronHashTable(isolate->heap()->locals_block_list_cache())) {
464 isolate->LocalsBlockListCacheGet(scope_info);
465 if (IsStringSet(maybe_outer_block_list) &&
468 PrintF(
" - name is blocklisted. Aborting.\n");
475 }
while (follow_context_chain);
478 PrintF(
"=> no property/slot found\n");
490 int side_data_index =
496 if (!IsContextSidePropertyCell(
object)) {
499 object = *isolate->factory()->NewContextSidePropertyCell(property);
500 side_data->set(side_data_index,
object);
505std::optional<ContextSidePropertyCell::Property>
510 int side_data_index =
515 if (IsUndefined(
object))
return {};
516 if (IsContextSidePropertyCell(
object)) {
524std::optional<int32_t> DoubleFitsInInt32(
double value) {
525 constexpr double int32_min = std::numeric_limits<int32_t>::min();
526 constexpr double int32_max = std::numeric_limits<int32_t>::max();
528 if (value == 0.0 && std::signbit(value))
return {};
529 double trunc_value = std::trunc(value);
530 if (int32_min <= value && value <= int32_max && value == trunc_value) {
531 return static_cast<int32_t
>(trunc_value);
536DirectHandle<Object> TryLoadMutableHeapNumber(
537 DirectHandle<Context> script_context,
int index, DirectHandle<Object> value,
540 DCHECK(script_context->IsScriptContext());
541 if (!IsHeapNumber(*value))
return value;
545 if (side_data_table == ReadOnlyRoots(isolate).empty_fixed_array()) {
564 side_data_table->set(side_data_index,
Smi::FromInt(property));
569 return isolate->factory()->NewHeapNumber(
static_cast<double>(int32_value));
571 return isolate->factory()->NewHeapNumber(
Cast<HeapNumber>(*value)->value());
583 return TryLoadMutableHeapNumber(
script_context, index, value, isolate);
598 if (*side_data ==
ReadOnlyRoots(isolate).empty_fixed_array()) {
606 if (IsTheHole(*old_value)) {
615 if (*old_value == *new_value) {
623 if (old_number == new_number && old_number != 0) {
631 std::optional<Tagged<ContextSidePropertyCell>> maybe_cell;
639 property = maybe_cell.value()->context_side_property();
646 isolate, maybe_cell.value(),
649 if (
v8_flags.script_context_mutable_heap_number) {
651 if (IsHeapNumber(*new_value)) {
653 auto maybe_int32_value = DoubleFitsInInt32(double_value);
654 if (
v8_flags.script_context_mutable_heap_int32 && maybe_int32_value) {
656 isolate->factory()->NewHeapInt32(*maybe_int32_value);
658 side_data->set(side_data_index,
661 auto new_number = isolate->factory()->NewHeapNumber(double_value);
663 side_data->set(side_data_index,
668 side_data->set(side_data_index,
682 if (
IsSmi(*new_value)) {
687 isolate, maybe_cell.value(),
691 if (IsHeapNumber(*new_value)) {
693 auto maybe_int32_value = DoubleFitsInInt32(double_value);
694 if (
v8_flags.script_context_mutable_heap_int32 && maybe_int32_value) {
696 isolate->factory()->NewHeapInt32(*maybe_int32_value);
698 side_data->set(side_data_index,
701 auto new_number = isolate->factory()->NewHeapNumber(double_value);
703 side_data->set(side_data_index,
713 CHECK(IsHeapNumber(*old_value));
715 if (
IsSmi(*new_value)) {
716 old_number->set_value_as_bits(
719 }
else if (IsHeapNumber(*new_value)) {
721 auto maybe_int32_value = DoubleFitsInInt32(double_value);
722 if (
v8_flags.script_context_mutable_heap_int32 && maybe_int32_value) {
723 old_number->set_value_as_bits(
729 isolate, maybe_cell.value(),
732 old_number->set_value(double_value);
733 side_data->set(side_data_index,
739 isolate, maybe_cell.value(),
749 CHECK(IsHeapNumber(*old_value));
750 if (
IsSmi(*new_value)) {
752 static_cast<double>(
Cast<Smi>(*new_value).value()));
753 }
else if (IsHeapNumber(*new_value)) {
759 isolate, maybe_cell.value(),
769 DCHECK(!maybe_cell.has_value());
779 return array->map() == js_array_template_literal_object_map();
783 Isolate* isolate = GetIsolate();
786 return isolate->factory()->NewStringFromStaticChars(
787 "Code generation from strings disallowed for this context");
791 Isolate* isolate = GetIsolate();
794 return isolate->factory()->NewStringFromStaticChars(
795 "Wasm code generation disallowed by embedder");
804 return IsInternalizedString(
extension) &&
810 CHECK(scope_info()->HasContextExtensionSlot());
813 if (IsJSContextExtensionObject(
extension)) {
821 }
else if (IsNativeContext(*
this)) {
832 DCHECK(scope_info()->HasContextExtensionSlot());
834 if (
v8_flags.verify_heap) VerifyExtensionSlot(
object);
841bool Context::IsBootstrappingOrValidParentContext(
Tagged<Object> object,
845 if (child->GetIsolate()->bootstrapper()->IsActive())
return true;
846 if (!IsContext(
object))
return false;
848 return IsNativeContext(context) || context->IsScriptContext() ||
849 context->IsModuleContext() || !child->IsModuleContext();
857 int previous_value = errors_thrown().value();
872static_assert(NativeContext::kStartOfStrongFieldsOffset ==
874static_assert(NativeContext::kStartOfWeakFieldsOffset ==
876static_assert(NativeContext::kMicrotaskQueueOffset ==
878static_assert(NativeContext::kSize ==
882#ifdef V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS
886 Isolate* isolate = promise->GetIsolate();
887 DCHECK(isolate->HasContextPromiseHooks());
892 contextSlot = PROMISE_HOOK_INIT_FUNCTION_INDEX;
895 contextSlot = PROMISE_HOOK_RESOLVE_FUNCTION_INDEX;
898 contextSlot = PROMISE_HOOK_BEFORE_FUNCTION_INDEX;
901 contextSlot = PROMISE_HOOK_AFTER_FUNCTION_INDEX;
907 DirectHandle<Object> hook(isolate->native_context()->get(contextSlot),
909 if (IsUndefined(*hook))
return;
912 DirectHandle<Object> argv[2] = {
Cast<Object>(promise), parent};
914 DirectHandle<Object>
receiver = isolate->global_proxy();
916 StackLimitCheck check(isolate);
918 if (check.HasOverflowed()) {
919 isolate->StackOverflow();
925 DCHECK(isolate->has_exception());
926 DirectHandle<Object> exception(isolate->exception(), isolate);
928 MessageLocation* no_location =
nullptr;
929 DirectHandle<JSMessageObject> message =
930 isolate->CreateMessageOrAbort(exception, no_location);
933 isolate->clear_exception();
V8_INLINE T FromMaybe(const T &default_value) const
V8_INLINE T FromJust() const &
V8_INLINE bool IsNothing() const
static Tagged< Smi > SmiMarker()
static Tagged< Smi > Other()
static Tagged< Smi > MutableInt32()
static Property FromSmi(Tagged< Smi > smi)
static Tagged< Smi > Const()
static Tagged< Smi > MutableHeapNumber()
static Tagged< ContextSidePropertyCell > GetOrCreateContextSidePropertyCell(DirectHandle< Context > context, size_t index, ContextSidePropertyCell::Property property, Isolate *isolate)
bool IsModuleContext() const
std::optional< ContextSidePropertyCell::Property > GetScriptContextSideProperty(size_t index) const
bool IsDebugEvaluateContext() const
static Handle< Object > Lookup(Handle< Context > context, Handle< String > name, ContextLookupFlags flags, int *index, PropertyAttributes *attributes, InitializationFlag *init_flag, VariableMode *variable_mode, bool *is_sloppy_function_name=nullptr)
Tagged< Context > declaration_context() const
void Initialize(Isolate *isolate)
bool IsWithContext() const
static const int kExtensionOffset
static DirectHandle< Object > LoadScriptContextElement(DirectHandle< Context > script_context, int index, DirectHandle< Object > new_value, Isolate *isolate)
V8_INLINE void set(int index, Tagged< Object > value, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
V8_EXPORT_PRIVATE Tagged< JSGlobalObject > global_object() const
bool IsBlockContext() const
Tagged< Context > closure_context() const
static V8_INLINE constexpr int OffsetOfElementAt(int index)
bool IsScriptContext() const
bool IsEvalContext() const
V8_EXPORT_PRIVATE void set_extension(Tagged< HeapObject > object, WriteBarrierMode mode=UPDATE_WRITE_BARRIER)
bool IsCatchContext() const
static V8_INLINE constexpr int SizeFor(int length)
bool is_declaration_context() const
Handle< Object > ErrorMessageForCodeGenerationFromStrings()
bool IsFunctionContext() const
@ MIN_CONTEXT_EXTENDED_SLOTS
@ CONTEXT_SIDE_TABLE_PROPERTY_INDEX
DirectHandle< Object > ErrorMessageForWasmCodeGeneration()
static const int kScopeInfoOffset
static void StoreScriptContextAndUpdateSlotProperty(DirectHandle< Context > script_context, int index, DirectHandle< Object > new_value, Isolate *isolate)
Tagged< HeapObject > extension() const
Tagged< JSObject > extension_object() const
V8_EXPORT_PRIVATE Tagged< JSGlobalProxy > global_proxy() const
static const int kNotFound
V8_INLINE Tagged< Object > get(int index) const
Tagged< JSReceiver > extension_receiver() const
Tagged< Context > script_context() const
static const int kPreviousOffset
Tagged< NativeContext > native_context() const
Tagged< SourceTextModule > module() const
@ kScriptContextSlotPropertyChangedGroup
static void DeoptimizeDependencyGroups(Isolate *isolate, ObjectT object, DependencyGroups groups)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > Call(Isolate *isolate, DirectHandle< Object > callable, DirectHandle< Object > receiver, base::Vector< const DirectHandle< Object > > args)
Isolate * isolate() const
static V8_WARN_UNUSED_RESULT Maybe< PropertyAttributes > GetOwnPropertyAttributes(Isolate *isolate, DirectHandle< JSReceiver > object, DirectHandle< Name > name)
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(Isolate *isolate, DirectHandle< JSReceiver > receiver, const char *key)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > HasProperty(LookupIterator *it)
static V8_EXPORT_PRIVATE void ReportMessage(Isolate *isolate, const MessageLocation *loc, DirectHandle< JSMessageObject > message)
static Handle< NameToIndexHashTable > Add(IsolateT *isolate, Handle< NameToIndexHashTable > table, DirectHandle< Name > key, int32_t value)
static uint32_t Hash(ReadOnlyRoots roots, DirectHandle< Name > key)
void IncrementErrorsThrown()
bool HasTemplateLiteralObject(Tagged< JSArray > array)
static V8_EXPORT_PRIVATE bool BooleanValue(Tagged< Object > obj, IsolateT *isolate)
static LocalNamesRange< DirectHandle< ScopeInfo > > IterateLocalNames(DirectHandle< ScopeInfo > scope_info)
static bool VariableIsSynthetic(Tagged< String > name)
Tagged< NameToIndexHashTable > names_to_context_index() const
static Handle< ScriptContextTable > New(Isolate *isolate, int capacity, AllocationType allocation=AllocationType::kYoung)
V8_WARN_UNUSED_RESULT static V8_EXPORT_PRIVATE Handle< ScriptContextTable > Add(Isolate *isolate, Handle< ScriptContextTable > table, DirectHandle< Context > script_context, bool ignore_duplicates)
Tagged< Context > get(int index) const
V8_WARN_UNUSED_RESULT V8_EXPORT_PRIVATE bool Lookup(DirectHandle< String > name, VariableLookupResult *result)
static constexpr Tagged< Smi > FromInt(int value)
static CellIndexKind GetCellIndexKind(int cell_index)
static Handle< ScriptContextTable > Allocate(IsolateT *isolate, int capacity, std::optional< DisallowGarbageCollection > *no_gc_out, AllocationType allocation=AllocationType::kYoung)
static void CopyElements(Isolate *isolate, Tagged< ScriptContextTable > dst, int dst_index, Tagged< ScriptContextTable > src, int src_index, int len, WriteBarrierMode mode=kDefaultMode)
static constexpr int kMaxCapacity
static constexpr int NewCapacityForIndex(int index, int old_capacity)
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
ZoneVector< RpoNumber > & result
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
bool is_sloppy(LanguageMode language_mode)
bool Is(IndirectHandle< U > value)
static PropertyAttributes GetAttributesForMode(VariableMode mode)
void PrintF(const char *format,...)
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
kInterpreterTrampolineOffset Tagged< HeapObject >
kStaticElementsTemplateOffset kInstancePropertiesTemplateOffset Tagged< FixedArray >
void MemsetTagged(Tagged_t *start, Tagged< MaybeObject > value, size_t counter)
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage report a tick only when allocated zone memory changes by this amount TracingFlags::gc_stats TracingFlags::gc_stats track native contexts that are expected to be garbage collected verify heap pointers before and after GC memory reducer runs GC with ReduceMemoryFootprint flag Maximum number of memory reducer GCs scheduled Old gen GC speed is computed directly from gc tracer counters Perform compaction on full GCs based on V8 s default heuristics Perform compaction on every full GC Perform code space compaction when finalizing a full GC with stack Stress GC compaction to flush out bugs with moving objects flush of baseline code when it has not been executed recently Use time base code flushing instead of age Use a progress bar to scan large objects in increments when incremental marking is active force incremental marking for small heaps and run it more often force marking at random points between and force scavenge at random points between and reclaim otherwise unreachable unmodified wrapper objects when possible less compaction in non memory reducing mode use high priority threads for concurrent Marking Test mode only flag It allows an unit test to select evacuation candidates use incremental marking for CppHeap cppheap_concurrent_marking c value for membalancer A special constant to balance between memory and space tradeoff The smaller the more memory it uses enable use of SSE4 instructions if available enable use of AVX VNNI instructions if available enable use of POPCNT instruction if available force all emitted branches to be in long mode(MIPS/PPC only)") DEFINE_BOOL(partial_constant_pool
constexpr int kSystemPointerSize
void ShortPrint(Tagged< Object > obj, FILE *out)
V8_EXPORT_PRIVATE FlagValues v8_flags
static Maybe< bool > UnscopableLookup(LookupIterator *it, bool is_with_context)
constexpr uint32_t kHoleNanUpper32
bool IsSerializableVariableMode(VariableMode mode)
bool IsImmutableLexicalOrPrivateVariableMode(VariableMode mode)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
static constexpr ReleaseStoreTag kReleaseStore
static constexpr AcquireLoadTag kAcquireLoad
Maybe< T > Just(const T &t)
#define DCHECK_LE(v1, v2)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
InitializationFlag init_flag