Commit 3a366c4d authored by Seth Brenith's avatar Seth Brenith Committed by Commit Bot

Privatize FixedArray-style accessors on ScopeInfo

This is a partial reland of https://crrev.com/c/2601880 .

In preparation for ScopeInfo not being a FixedArrayBase, this change
privatizes the FixedArray-style functions that provide access to
ScopeInfo fields by index, and moves them from scope-info-inl.h to
scope-info.cc. Those functions are still used pretty heavily during
initialization (ScopeInfo::Create, etc.), but at least we can avoid
presenting them to the rest of the world.

This change also introduces a new length() function in ScopeInfo which
hides the one inherited from FixedArrayBase and computes the ScopeInfo's
length based on its flags, so that there are no remaining readers of the
'length' field.

Change-Id: I609754010723b679e5cf00f386020faaab84c17a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2718275
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73151}
parent 4fe89e59
......@@ -740,8 +740,7 @@ void ScopeIterator::VisitModuleScope(const Visitor& visitor) const {
if (VisitContextLocals(visitor, scope_info, context_, ScopeTypeModule))
return;
int count_index = scope_info->ModuleVariableCountIndex();
int module_variable_count = Smi::cast(scope_info->get(count_index)).value();
int module_variable_count = scope_info->ModuleVariableCount();
Handle<SourceTextModule> module(context_->module(), isolate_);
......
......@@ -2273,18 +2273,13 @@ void JSSegments::JSSegmentsPrint(std::ostream& os) { // NOLINT
namespace {
void PrintScopeInfoList(ScopeInfo scope_info, std::ostream& os,
const char* list_name, int nof_internal_slots,
int start, int length) {
const char* list_name, int length) {
if (length <= 0) return;
int end = start + length;
os << "\n - " << list_name;
if (nof_internal_slots > 0) {
os << " " << start << "-" << end << " [internal slots]";
}
os << " {\n";
for (int i = nof_internal_slots; start < end; ++i, ++start) {
for (int i = 0; i < length; ++i) {
os << " - " << i << ": ";
String::cast(scope_info.get(start)).ShortPrint(os);
scope_info.context_local_names(i).ShortPrint(os);
os << "\n";
}
os << " }";
......@@ -2341,8 +2336,7 @@ void ScopeInfo::ScopeInfoPrint(std::ostream& os) { // NOLINT
}
os << "\n - length: " << length();
if (length() > 0) {
PrintScopeInfoList(*this, os, "context slots", Context::MIN_CONTEXT_SLOTS,
ContextLocalNamesIndex(), ContextLocalCount());
PrintScopeInfoList(*this, os, "context slots", ContextLocalCount());
// TODO(neis): Print module stuff if present.
}
os << "\n";
......
......@@ -30,49 +30,7 @@ int ScopeInfo::Flags() const { return flags(); }
int ScopeInfo::ParameterCount() const { return parameter_count(); }
int ScopeInfo::ContextLocalCount() const { return context_local_count(); }
Object ScopeInfo::get(int index) const {
IsolateRoot isolate = GetIsolateForPtrCompr(*this);
return get(isolate, index);
}
Object ScopeInfo::get(IsolateRoot isolate, int index) const {
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
return TaggedField<Object>::Relaxed_Load(
isolate, *this, FixedArray::OffsetOfElementAt(index));
}
void ScopeInfo::set(int index, Smi value) {
DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
DCHECK(Object(value).IsSmi());
int offset = FixedArray::OffsetOfElementAt(index);
RELAXED_WRITE_FIELD(*this, offset, value);
}
void ScopeInfo::set(int index, Object value, WriteBarrierMode mode) {
DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
DCHECK(IsScopeInfo());
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
int offset = FixedArray::OffsetOfElementAt(index);
RELAXED_WRITE_FIELD(*this, offset, value);
CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
}
void ScopeInfo::CopyElements(Isolate* isolate, int dst_index, ScopeInfo src,
int src_index, int len, WriteBarrierMode mode) {
if (len == 0) return;
DCHECK_LE(dst_index + len, length());
DCHECK_LE(src_index + len, src.length());
DisallowGarbageCollection no_gc;
ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
ObjectSlot src_slot(src.RawFieldOfElementAt(src_index));
isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
}
ObjectSlot ScopeInfo::RawFieldOfElementAt(int index) {
return RawField(FixedArray::OffsetOfElementAt(index));
}
ObjectSlot ScopeInfo::data_start() { return RawField(OffsetOfElementAt(0)); }
} // namespace internal
} // namespace v8
......
......@@ -15,17 +15,12 @@
#include "src/objects/string-set-inl.h"
#include "src/roots/roots.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
// An entry in ModuleVariableEntries consists of several slots:
enum ModuleVariableEntryOffset {
kModuleVariableNameOffset,
kModuleVariableIndexOffset,
kModuleVariablePropertiesOffset,
kModuleVariableEntryLength // Sentinel value.
};
#ifdef DEBUG
bool ScopeInfo::Equals(ScopeInfo other) const {
if (length() != other.length()) return false;
......@@ -164,6 +159,12 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
scope->AsModuleScope()->module());
}
// Make sure the Fields enum agrees with Torque-generated offsets.
#define ASSERT_MATCHED_FIELD(name) \
STATIC_ASSERT(OffsetOfElementAt(k##name) == k##name##Offset);
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(ASSERT_MATCHED_FIELD)
#undef ASSERT_MATCHED_FIELD
const int length = kVariablePartIndex + 2 * context_local_count +
(should_save_class_variable_index ? 1 : 0) +
(has_receiver ? 1 : 0) +
......@@ -228,6 +229,12 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
scope_info.set_parameter_count(parameter_count);
scope_info.set_context_local_count(context_local_count);
// Jump ahead to set the number of module variables so that we can use range
// DCHECKs in future steps.
if (scope->is_module_scope()) {
scope_info.set_module_variable_count(module_vars_count);
}
// Add context locals' names and info, module variables' names and info.
// Context locals are added using their index.
int context_local_base = index;
......@@ -255,18 +262,26 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
break;
}
case VariableLocation::MODULE: {
scope_info.set(module_var_entry + kModuleVariableNameOffset,
scope_info.set(module_var_entry +
TorqueGeneratedModuleVariableOffsets::kNameOffset /
kTaggedSize,
*var->name(), mode);
scope_info.set(module_var_entry + kModuleVariableIndexOffset,
Smi::FromInt(var->index()));
scope_info.set(
module_var_entry +
TorqueGeneratedModuleVariableOffsets::kIndexOffset /
kTaggedSize,
Smi::FromInt(var->index()));
uint32_t properties =
VariableModeBits::encode(var->mode()) |
InitFlagBit::encode(var->initialization_flag()) |
MaybeAssignedFlagBit::encode(var->maybe_assigned()) |
ParameterNumberBits::encode(ParameterNumberBits::kMax) |
IsStaticFlagBit::encode(var->is_static_flag());
scope_info.set(module_var_entry + kModuleVariablePropertiesOffset,
Smi::FromInt(properties));
scope_info.set(
module_var_entry +
TorqueGeneratedModuleVariableOffsets::kPropertiesOffset /
kTaggedSize,
Smi::FromInt(properties));
module_var_entry += kModuleVariableEntryLength;
break;
}
......@@ -371,7 +386,8 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
DCHECK_EQ(index, scope_info.ModuleInfoIndex());
scope_info.set(index++, *module_info);
DCHECK_EQ(index, scope_info.ModuleVariableCountIndex());
scope_info.set(index++, Smi::FromInt(module_vars_count));
// Module variable count was already written above.
index++;
DCHECK_EQ(index, scope_info.ModuleVariablesIndex());
// The variable entries themselves have already been written above.
index += kModuleVariableEntryLength * module_vars_count;
......@@ -556,6 +572,53 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
return scope_info;
}
Object ScopeInfo::get(int index) const {
IsolateRoot isolate = GetIsolateForPtrCompr(*this);
return get(isolate, index);
}
Object ScopeInfo::get(IsolateRoot isolate, int index) const {
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
return TaggedField<Object>::Relaxed_Load(isolate, *this,
OffsetOfElementAt(index));
}
void ScopeInfo::set(int index, Smi value) {
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
DCHECK(Object(value).IsSmi());
int offset = OffsetOfElementAt(index);
RELAXED_WRITE_FIELD(*this, offset, value);
}
void ScopeInfo::set(int index, Object value, WriteBarrierMode mode) {
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
int offset = OffsetOfElementAt(index);
RELAXED_WRITE_FIELD(*this, offset, value);
CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
}
void ScopeInfo::CopyElements(Isolate* isolate, int dst_index, ScopeInfo src,
int src_index, int len, WriteBarrierMode mode) {
if (len == 0) return;
DCHECK_LE(src_index + len, src.length());
DisallowGarbageCollection no_gc;
ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
ObjectSlot src_slot(src.RawFieldOfElementAt(src_index));
isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
}
ObjectSlot ScopeInfo::RawFieldOfElementAt(int index) {
return RawField(OffsetOfElementAt(index));
}
int ScopeInfo::length() const {
// AllocatedSize() is generated by Torque and represents the size in bytes of
// the object, as computed from flags, context_local_count, and possibly
// module_variable_count. Convert that size into a number of slots.
return (AllocatedSize() - FixedArray::kHeaderSize) / kTaggedSize;
}
// static
Handle<ScopeInfo> ScopeInfo::RecreateWithBlockList(
Isolate* isolate, Handle<ScopeInfo> original, Handle<StringSet> blocklist) {
......@@ -836,6 +899,11 @@ bool ScopeInfo::VariableIsSynthetic(String name) {
name.Equals(name.GetReadOnlyRoots().this_string());
}
int ScopeInfo::ModuleVariableCount() const {
DCHECK_EQ(scope_type(), MODULE_SCOPE);
return module_variable_count();
}
int ScopeInfo::ModuleIndex(String name, VariableMode* mode,
InitializationFlag* init_flag,
MaybeAssignedFlag* maybe_assigned_flag) {
......@@ -847,15 +915,13 @@ int ScopeInfo::ModuleIndex(String name, VariableMode* mode,
DCHECK_NOT_NULL(maybe_assigned_flag);
int module_vars_count = module_variable_count();
int entry = ModuleVariablesIndex();
for (int i = 0; i < module_vars_count; ++i) {
String var_name = String::cast(get(entry + kModuleVariableNameOffset));
String var_name = module_variables_name(i);
if (name.Equals(var_name)) {
int index;
ModuleVariable(i, nullptr, &index, mode, init_flag, maybe_assigned_flag);
return index;
}
entry += kModuleVariableEntryLength;
}
return 0;
......@@ -875,11 +941,11 @@ int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
if (scope_info.IsEmpty()) return -1;
int start = scope_info.ContextLocalNamesIndex();
int end = start + scope_info.context_local_count();
for (int i = start; i < end; ++i) {
if (name != scope_info.get(i)) continue;
int var = i - start;
int context_local_count = scope_info.context_local_count();
for (int var = 0; var < context_local_count; ++var) {
if (name != scope_info.context_local_names(var)) {
continue;
}
*mode = scope_info.ContextLocalMode(var);
*is_static_flag = scope_info.ContextLocalIsStaticFlag(var);
*init_flag = scope_info.ContextLocalInitFlag(var);
......@@ -1147,3 +1213,5 @@ FixedArray SourceTextModuleInfo::RegularExportExportNames(int i) const {
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
......@@ -45,19 +45,6 @@ class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, FixedArrayBase> {
DECL_PRINTER(ScopeInfo)
DECL_VERIFIER(ScopeInfo)
// For refactoring, clone some FixedArray member functions. Eventually this
// class will stop pretending to be a FixedArray, but we're not quite there.
inline Object get(int index) const;
inline Object get(IsolateRoot isolate, int index) const;
// Setter that doesn't need write barrier.
inline void set(int index, Smi value);
// Setter with explicit barrier mode.
inline void set(int index, Object value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
inline void CopyElements(Isolate* isolate, int dst_index, ScopeInfo src,
int src_index, int len, WriteBarrierMode mode);
inline ObjectSlot RawFieldOfElementAt(int index);
class BodyDescriptor;
// Return the type of this scope.
......@@ -180,6 +167,8 @@ class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, FixedArrayBase> {
InitializationFlag* init_flag,
MaybeAssignedFlag* maybe_assigned_flag);
int ModuleVariableCount() const;
// Lookup support for serialized scope info. Returns the function context
// slot index if the function name is present and context-allocated (named
// function expressions, only), otherwise returns a value < 0. The name
......@@ -272,17 +261,17 @@ class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, FixedArrayBase> {
kVariablePartIndex
};
// Make sure the Fields enum agrees with Torque-generated offsets.
#define ASSERT_MATCHED_FIELD(name) \
STATIC_ASSERT(FixedArray::OffsetOfElementAt(k##name) == k##name##Offset);
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(ASSERT_MATCHED_FIELD)
#undef ASSERT_MATCHED_FIELD
STATIC_ASSERT(LanguageModeSize == 1 << LanguageModeBit::kSize);
STATIC_ASSERT(kLastFunctionKind <= FunctionKindBits::kMax);
bool IsEmpty() const;
// Returns the size in bytes for a ScopeInfo with |length| slots.
static constexpr int SizeFor(int length) { return OffsetOfElementAt(length); }
// Gives access to raw memory which stores the ScopeInfo's data.
inline ObjectSlot data_start();
private:
int ContextLocalNamesIndex() const;
int ContextLocalInfosIndex() const;
......@@ -299,10 +288,33 @@ class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, FixedArrayBase> {
static bool NeedsPositionInfo(ScopeType type);
// Converts byte offsets within the object to FixedArray-style indices.
// Raw access by slot index. These functions rely on the fact that everything
// in ScopeInfo is tagged. Each slot is tagged-pointer sized. Slot 0 is
// 'flags', the first field defined by ScopeInfo after the standard-size
// HeapObject header.
V8_EXPORT_PRIVATE Object get(int index) const;
Object get(IsolateRoot isolate, int index) const;
// Setter that doesn't need write barrier.
void set(int index, Smi value);
// Setter with explicit barrier mode.
void set(int index, Object value,
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
void CopyElements(Isolate* isolate, int dst_index, ScopeInfo src,
int src_index, int len, WriteBarrierMode mode);
ObjectSlot RawFieldOfElementAt(int index);
// The number of tagged-pointer-sized slots in the ScopeInfo after its
// standard HeapObject header.
V8_EXPORT_PRIVATE int length() const;
// Conversions between offset (bytes from the beginning of the object) and
// index (number of tagged-pointer-sized slots starting after the standard
// HeapObject header).
static constexpr int OffsetOfElementAt(int index) {
return FixedArray::kHeaderSize + index * kTaggedSize;
}
static constexpr int ConvertOffsetToIndex(int offset) {
int index = (offset - FixedArray::kHeaderSize) / kTaggedSize;
CONSTEXPR_DCHECK(FixedArray::OffsetOfElementAt(index) == offset);
CONSTEXPR_DCHECK(OffsetOfElementAt(index) == offset);
return index;
}
......@@ -322,8 +334,12 @@ class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, FixedArrayBase> {
InitializationFlag* init_flag = nullptr,
MaybeAssignedFlag* maybe_assigned_flag = nullptr);
static const int kFunctionNameEntries = 2;
static const int kPositionInfoEntries = 2;
static const int kFunctionNameEntries =
TorqueGeneratedFunctionVariableInfoOffsets::kSize / kTaggedSize;
static const int kPositionInfoEntries =
TorqueGeneratedPositionInfoOffsets::kSize / kTaggedSize;
static const int kModuleVariableEntryLength =
TorqueGeneratedModuleVariableOffsets::kSize / kTaggedSize;
// Properties of variables.
DEFINE_TORQUE_GENERATED_VARIABLE_PROPERTIES()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment