[torque] Begin porting ScopeInfo to Torque

This change adds Torque field definitions for ScopeInfo and begins to
use the Torque-generated accessors in some places. It does not change
the in-memory layout of ScopeInfo.

Torque compiler changes:

- Fix an issue where the parser created constexpr types for classes
  based on the class name rather than the `generates` clause. This meant
  that generated accessors referred to the imaginary type HashTable
  rather than the real C++ type FixedArray.
- Don't pass Isolate* through the generated runtime functions that
  implement Torque macros. Maybe we'll need it eventually, but we don't
  right now and it complicates a lot of things.
- Don't emit `kSomeFieldOffset` if some_field has an unknown offset.
  Instead, emit a member function `SomeFieldOffset()` which fetches the
  slice for some_field and returns its offset.
- Emit an `AllocatedSize()` member function for classes which have
  complex length expressions. It fetches the slice for the last field
  and performs the multiply&add to compute the total object size.
- Emit field accessors for fields with complex length expressions, using
  the new offset functions.
- Fix a few minor bugs where Torque can write uncompilable code.

With this change, most code still treats ScopeInfo like a FixedArray, so
I would like to follow up with some additional changes:

1. Generate a GC visitor for ScopeInfo and use it
2. Generate accessors for struct-typed fields (indexed or otherwise),
   and use them
3. Get rid of the FixedArray-style get and set accessors; use
   TaggedField::load and similar instead
4. Inherit from HeapObject rather than FixedArrayBase to remove the
   unnecessary `length` field

After that, there will only be one ugly part left: initialization. I
think it's possible to generate a factory function that takes a bunch of
iterator parameters and returns a fully-formed, verifiably correct
ScopeInfo instance, but doing so is more complicated than the four
mostly-mechanical changes listed above.

Bug: v8:7793
Change-Id: I55fcfe9189e4d1613c68d49e378da5dc02597b36
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2357758
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: Dominik Inführ <dinfuehr@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#72187}
This commit is contained in:
Seth Brenith 2021-01-19 10:20:26 -08:00 committed by Commit Bot
parent 1dd3e29b52
commit ecaac3292f
30 changed files with 660 additions and 367 deletions

View File

@ -1192,6 +1192,7 @@ action("postmortem-metadata") {
"src/objects/primitive-heap-object.h",
"src/objects/primitive-heap-object-inl.h",
"src/objects/scope-info.h",
"src/objects/scope-info-inl.h",
"src/objects/script.h",
"src/objects/script-inl.h",
"src/objects/shared-function-info.cc",
@ -3184,6 +3185,7 @@ v8_source_set("v8_base_without_compiler") {
"src/objects/prototype-info.h",
"src/objects/prototype.h",
"src/objects/regexp-match-info.h",
"src/objects/scope-info-inl.h",
"src/objects/scope-info.cc",
"src/objects/scope-info.h",
"src/objects/script-inl.h",

View File

@ -2013,6 +2013,11 @@ TNode<IntPtrT> CodeStubAssembler::LoadArrayLength(
return LoadAndUntagWeakFixedArrayLength(array);
}
template <>
TNode<IntPtrT> CodeStubAssembler::LoadArrayLength(TNode<ScopeInfo> array) {
return LoadAndUntagFixedArrayBaseLength(array);
}
template <typename Array, typename TIndex, typename TValue>
TNode<TValue> CodeStubAssembler::LoadArrayElement(
TNode<Array> array, int array_header_size, TNode<TIndex> index_node,
@ -2043,6 +2048,10 @@ TNode<TValue> CodeStubAssembler::LoadArrayElement(
template V8_EXPORT_PRIVATE TNode<MaybeObject>
CodeStubAssembler::LoadArrayElement<TransitionArray, IntPtrT>(
TNode<TransitionArray>, int, TNode<IntPtrT>, int, LoadSensitivity);
template V8_EXPORT_PRIVATE TNode<MaybeObject>
CodeStubAssembler::LoadArrayElement<ScopeInfo, IntPtrT>(TNode<ScopeInfo>, int,
TNode<IntPtrT>, int,
LoadSensitivity);
template <typename TIndex>
TNode<Object> CodeStubAssembler::LoadFixedArrayElement(

View File

@ -182,7 +182,6 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case NUMBER_DICTIONARY_TYPE:
case SIMPLE_NUMBER_DICTIONARY_TYPE:
case EPHEMERON_HASH_TABLE_TYPE:
case SCOPE_INFO_TYPE:
case SCRIPT_CONTEXT_TABLE_TYPE:
FixedArray::cast(*this).FixedArrayVerify(isolate);
break;
@ -581,6 +580,20 @@ void Context::ContextVerify(Isolate* isolate) {
}
}
void ScopeInfo::ScopeInfoVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::ScopeInfoVerify(*this, isolate);
// Make sure that the FixedArray-style length matches the length that we would
// compute based on the Torque indexed fields.
CHECK_EQ(FixedArray::SizeFor(length()), AllocatedSize());
// Code that treats ScopeInfo like a FixedArray expects all values to be
// tagged.
for (int i = 0; i < length(); ++i) {
Object::VerifyPointer(isolate, get(isolate, i));
}
}
void NativeContext::NativeContextVerify(Isolate* isolate) {
ContextVerify(isolate);
CHECK_EQ(length(), NativeContext::NATIVE_CONTEXT_SLOTS);

View File

@ -209,9 +209,6 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case STORE_HANDLER_TYPE:
StoreHandler::cast(*this).StoreHandlerPrint(os);
break;
case SCOPE_INFO_TYPE:
ScopeInfo::cast(*this).ScopeInfoPrint(os);
break;
case FEEDBACK_METADATA_TYPE:
FeedbackMetadata::cast(*this).FeedbackMetadataPrint(os);
break;

View File

@ -676,8 +676,11 @@ template <typename Impl>
Handle<ScopeInfo> FactoryBase<Impl>::NewScopeInfo(int length,
AllocationType type) {
DCHECK(type == AllocationType::kOld || type == AllocationType::kReadOnly);
return Handle<ScopeInfo>::cast(NewFixedArrayWithMap(
read_only_roots().scope_info_map_handle(), length, type));
Handle<HeapObject> result =
Handle<HeapObject>::cast(NewFixedArray(length, type));
result->set_map_after_allocation(*read_only_roots().scope_info_map_handle(),
SKIP_WRITE_BARRIER);
return Handle<ScopeInfo>::cast(result);
}
template <typename Impl>

View File

@ -14,46 +14,47 @@
namespace v8 {
namespace internal {
#define TYPED_VISITOR_ID_LIST(V) \
V(AllocationSite) \
V(BigInt) \
V(ByteArray) \
V(BytecodeArray) \
V(Cell) \
V(Code) \
V(CodeDataContainer) \
V(CoverageInfo) \
V(DataHandler) \
V(EmbedderDataArray) \
V(EphemeronHashTable) \
V(FeedbackCell) \
V(FeedbackMetadata) \
V(FixedDoubleArray) \
V(JSArrayBuffer) \
V(JSDataView) \
V(JSFunction) \
V(JSObject) \
V(JSTypedArray) \
V(WeakCell) \
V(JSWeakCollection) \
V(JSWeakRef) \
V(Map) \
V(NativeContext) \
V(PreparseData) \
V(PropertyArray) \
V(PropertyCell) \
V(PrototypeInfo) \
V(SmallOrderedHashMap) \
V(SmallOrderedHashSet) \
V(SmallOrderedNameDictionary) \
V(SourceTextModule) \
V(Symbol) \
V(SyntheticModule) \
V(TransitionArray) \
V(WasmArray) \
V(WasmIndirectFunctionTable) \
V(WasmInstanceObject) \
V(WasmStruct) \
#define TYPED_VISITOR_ID_LIST(V) \
V(AllocationSite) \
V(BigInt) \
V(ByteArray) \
V(BytecodeArray) \
V(Cell) \
V(Code) \
V(CodeDataContainer) \
V(CoverageInfo) \
V(DataHandler) \
V(EmbedderDataArray) \
V(EphemeronHashTable) \
V(FeedbackCell) \
V(FeedbackMetadata) \
V(FixedDoubleArray) \
V(JSArrayBuffer) \
V(JSDataView) \
V(JSFunction) \
V(JSObject) \
V(JSTypedArray) \
V(WeakCell) \
V(JSWeakCollection) \
V(JSWeakRef) \
V(Map) \
V(NativeContext) \
V(PreparseData) \
V(PropertyArray) \
V(PropertyCell) \
V(PrototypeInfo) \
V(ScopeInfo) \
V(SmallOrderedHashMap) \
V(SmallOrderedHashSet) \
V(SmallOrderedNameDictionary) \
V(SourceTextModule) \
V(Symbol) \
V(SyntheticModule) \
V(TransitionArray) \
V(WasmArray) \
V(WasmIndirectFunctionTable) \
V(WasmInstanceObject) \
V(WasmStruct) \
V(WasmTypeInfo)
#define FORWARD_DECLARE(TypeName) class TypeName;

View File

@ -532,16 +532,16 @@ bool Heap::CreateInitialMaps() {
AllocationType::kReadOnly);
if (!alloc.To(&obj)) return false;
obj.set_map_after_allocation(roots.scope_info_map(), SKIP_WRITE_BARRIER);
FixedArray::cast(obj).set_length(ScopeInfo::kVariablePartIndex);
ScopeInfo::cast(obj).set_length(ScopeInfo::kVariablePartIndex);
int flags = ScopeInfo::IsEmptyBit::encode(true);
DCHECK_EQ(ScopeInfo::LanguageModeBit::decode(flags), LanguageMode::kSloppy);
DCHECK_EQ(ScopeInfo::ReceiverVariableBits::decode(flags),
VariableAllocationInfo::NONE);
DCHECK_EQ(ScopeInfo::FunctionVariableBits::decode(flags),
VariableAllocationInfo::NONE);
ScopeInfo::cast(obj).SetFlags(flags);
ScopeInfo::cast(obj).SetContextLocalCount(0);
ScopeInfo::cast(obj).SetParameterCount(0);
ScopeInfo::cast(obj).set_flags(flags);
ScopeInfo::cast(obj).set_context_local_count(0);
ScopeInfo::cast(obj).set_parameter_count(0);
}
set_empty_scope_info(ScopeInfo::cast(obj));

View File

@ -3067,13 +3067,11 @@ void AccessorAssembler::ScriptContextTableLookup(
ScriptContextTable::kFirstContextSlotIndex * kTaggedSize));
TNode<ScopeInfo> scope_info =
CAST(LoadContextElement(script_context, Context::SCOPE_INFO_INDEX));
TNode<IntPtrT> length = LoadAndUntagFixedArrayBaseLength(scope_info);
GotoIf(IntPtrLessThanOrEqual(length, IntPtrConstant(0)), &loop);
TVARIABLE(IntPtrT, scope_var_index,
IntPtrConstant(ScopeInfo::kVariablePartIndex - 1));
TNode<IntPtrT> num_scope_vars = SmiUntag(CAST(LoadFixedArrayElement(
scope_info, IntPtrConstant(ScopeInfo::Fields::kContextLocalCount))));
TNode<IntPtrT> num_scope_vars = SmiUntag(
CAST(LoadObjectField(scope_info, ScopeInfo::kContextLocalCountOffset)));
TNode<IntPtrT> end_index = IntPtrAdd(
num_scope_vars, IntPtrConstant(ScopeInfo::kVariablePartIndex));
Label loop_scope_info(this, &scope_var_index);
@ -3085,8 +3083,9 @@ void AccessorAssembler::ScriptContextTableLookup(
GotoIf(IntPtrGreaterThanOrEqual(scope_var_index.value(), end_index),
&loop);
TNode<Object> var_name =
LoadFixedArrayElement(scope_info, scope_var_index.value(), 0);
FixedArrayBoundsCheck(scope_info, scope_var_index.value(), 0);
TNode<Object> var_name = CAST(LoadArrayElement(
scope_info, FixedArray::kHeaderSize, scope_var_index.value()));
GotoIf(TaggedNotEqual(var_name, name), &loop_scope_info);
TNode<IntPtrT> var_index =

View File

@ -68,6 +68,7 @@
#include "src/objects/property-cell-inl.h"
#include "src/objects/property-descriptor-object-inl.h"
#include "src/objects/prototype-info-inl.h"
#include "src/objects/scope-info-inl.h"
#include "src/objects/script-inl.h"
#include "src/objects/shared-function-info-inl.h"
#include "src/objects/slots-atomic-inl.h"

View File

@ -11,6 +11,7 @@
#include "src/objects/tagged-field.h"
#include "src/roots/roots.h"
#include "src/torque/runtime-macro-shims.h"
#include "src/torque/runtime-support.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

View File

@ -154,7 +154,6 @@ VisitorId Map::GetVisitorId(Map map) {
case GLOBAL_DICTIONARY_TYPE:
case NUMBER_DICTIONARY_TYPE:
case SIMPLE_NUMBER_DICTIONARY_TYPE:
case SCOPE_INFO_TYPE:
case SCRIPT_CONTEXT_TABLE_TYPE:
return kVisitFixedArray;
@ -190,6 +189,9 @@ VisitorId Map::GetVisitorId(Map map) {
case MAP_TYPE:
return kVisitMap;
case SCOPE_INFO_TYPE:
return kVisitScopeInfo;
case CODE_TYPE:
return kVisitCode;

View File

@ -32,46 +32,47 @@ enum InstanceType : uint16_t;
V(FeedbackMetadata) \
V(FixedDoubleArray)
#define POINTER_VISITOR_ID_LIST(V) \
V(AllocationSite) \
V(BytecodeArray) \
V(Cell) \
V(Code) \
V(CodeDataContainer) \
V(DataHandler) \
V(EmbedderDataArray) \
V(EphemeronHashTable) \
V(FeedbackCell) \
V(FreeSpace) \
V(JSApiObject) \
V(JSArrayBuffer) \
V(JSDataView) \
V(JSFunction) \
V(JSObject) \
V(JSObjectFast) \
V(JSTypedArray) \
V(JSWeakRef) \
V(JSWeakCollection) \
V(Map) \
V(NativeContext) \
V(PreparseData) \
V(PropertyArray) \
V(PropertyCell) \
V(PrototypeInfo) \
V(ShortcutCandidate) \
V(SmallOrderedHashMap) \
V(SmallOrderedHashSet) \
V(SmallOrderedNameDictionary) \
V(SourceTextModule) \
V(Struct) \
V(Symbol) \
V(SyntheticModule) \
V(TransitionArray) \
V(WasmIndirectFunctionTable) \
V(WasmInstanceObject) \
V(WasmArray) \
V(WasmStruct) \
V(WasmTypeInfo) \
#define POINTER_VISITOR_ID_LIST(V) \
V(AllocationSite) \
V(BytecodeArray) \
V(Cell) \
V(Code) \
V(CodeDataContainer) \
V(DataHandler) \
V(EmbedderDataArray) \
V(EphemeronHashTable) \
V(FeedbackCell) \
V(FreeSpace) \
V(JSApiObject) \
V(JSArrayBuffer) \
V(JSDataView) \
V(JSFunction) \
V(JSObject) \
V(JSObjectFast) \
V(JSTypedArray) \
V(JSWeakRef) \
V(JSWeakCollection) \
V(Map) \
V(NativeContext) \
V(PreparseData) \
V(PropertyArray) \
V(PropertyCell) \
V(PrototypeInfo) \
V(ScopeInfo) \
V(ShortcutCandidate) \
V(SmallOrderedHashMap) \
V(SmallOrderedHashSet) \
V(SmallOrderedNameDictionary) \
V(SourceTextModule) \
V(Struct) \
V(Symbol) \
V(SyntheticModule) \
V(TransitionArray) \
V(WasmIndirectFunctionTable) \
V(WasmInstanceObject) \
V(WasmArray) \
V(WasmStruct) \
V(WasmTypeInfo) \
V(WeakCell)
#define TORQUE_VISITOR_ID_LIST(V) \

View File

@ -898,7 +898,6 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case GLOBAL_DICTIONARY_TYPE:
case NUMBER_DICTIONARY_TYPE:
case SIMPLE_NUMBER_DICTIONARY_TYPE:
case SCOPE_INFO_TYPE:
case SCRIPT_CONTEXT_TABLE_TYPE:
return Op::template apply<FixedArray::BodyDescriptor>(p1, p2, p3, p4);
case EPHEMERON_HASH_TABLE_TYPE:
@ -997,6 +996,8 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case WASM_MODULE_OBJECT_TYPE:
case WASM_TABLE_OBJECT_TYPE:
return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4);
case SCOPE_INFO_TYPE:
return Op::template apply<ScopeInfo::BodyDescriptor>(p1, p2, p3, p4);
case WASM_INSTANCE_OBJECT_TYPE:
return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3,
p4);

View File

@ -34,7 +34,7 @@
#include "src/objects/property-details.h"
#include "src/objects/property.h"
#include "src/objects/regexp-match-info.h"
#include "src/objects/scope-info.h"
#include "src/objects/scope-info-inl.h"
#include "src/objects/shared-function-info.h"
#include "src/objects/slots-inl.h"
#include "src/objects/smi-inl.h"
@ -450,7 +450,6 @@ bool Object::IsMinusZero() const {
}
OBJECT_CONSTRUCTORS_IMPL(RegExpMatchInfo, FixedArray)
OBJECT_CONSTRUCTORS_IMPL(ScopeInfo, FixedArray)
OBJECT_CONSTRUCTORS_IMPL(BigIntBase, PrimitiveHeapObject)
OBJECT_CONSTRUCTORS_IMPL(BigInt, BigIntBase)
OBJECT_CONSTRUCTORS_IMPL(FreshlyAllocatedBigInt, BigIntBase)
@ -461,7 +460,6 @@ OBJECT_CONSTRUCTORS_IMPL(FreshlyAllocatedBigInt, BigIntBase)
CAST_ACCESSOR(BigIntBase)
CAST_ACCESSOR(BigInt)
CAST_ACCESSOR(RegExpMatchInfo)
CAST_ACCESSOR(ScopeInfo)
bool Object::HasValidElements() {
// Dictionary is covered under FixedArray. ByteArray is used
@ -1119,21 +1117,6 @@ static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Object> key,
PACKED_ELEMENTS, 2);
}
bool ScopeInfo::IsAsmModule() const { return IsAsmModuleBit::decode(Flags()); }
bool ScopeInfo::HasSimpleParameters() const {
return HasSimpleParametersBit::decode(Flags());
}
#define FIELD_ACCESSORS(name) \
void ScopeInfo::Set##name(int value) { set(k##name, Smi::FromInt(value)); } \
int ScopeInfo::name() const { \
DCHECK_GE(length(), kVariablePartIndex); \
return Smi::ToInt(get(k##name)); \
}
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS
FreshlyAllocatedBigInt FreshlyAllocatedBigInt::cast(Object object) {
SLOW_DCHECK(object.IsBigInt());
return FreshlyAllocatedBigInt(object.ptr());

View File

@ -2298,6 +2298,9 @@ int HeapObject::SizeFromMap(Map map) const {
return FeedbackVector::SizeFor(
FeedbackVector::unchecked_cast(*this).length());
}
if (instance_type == SCOPE_INFO_TYPE) {
return FixedArray::SizeFor(ScopeInfo::unchecked_cast(*this).length());
}
if (instance_type == BIGINT_TYPE) {
return BigInt::SizeFor(BigInt::unchecked_cast(*this).length());
}

View File

@ -0,0 +1,82 @@
// Copyright 2020 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_OBJECTS_SCOPE_INFO_INL_H_
#define V8_OBJECTS_SCOPE_INFO_INL_H_
#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/scope-info.h"
#include "src/objects/string.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
#include "torque-generated/src/objects/scope-info-tq-inl.inc"
TQ_OBJECT_CONSTRUCTORS_IMPL(ScopeInfo)
bool ScopeInfo::IsAsmModule() const { return IsAsmModuleBit::decode(Flags()); }
bool ScopeInfo::HasSimpleParameters() const {
return HasSimpleParametersBit::decode(Flags());
}
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));
}
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_SCOPE_INFO_INL_H_

View File

@ -11,6 +11,7 @@
#include "src/init/bootstrapper.h"
#include "src/objects/module-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/scope-info-inl.h"
#include "src/objects/string-set-inl.h"
#include "src/roots/roots.h"
@ -157,6 +158,12 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
: 0;
const bool has_outer_scope_info = !outer_scope.is_null();
Handle<SourceTextModuleInfo> module_info;
if (scope->is_module_scope()) {
module_info = SourceTextModuleInfo::New(isolate, zone,
scope->AsModuleScope()->module());
}
const int length = kVariablePartIndex + 2 * context_local_count +
(should_save_class_variable_index ? 1 : 0) +
(has_receiver ? 1 : 0) +
@ -216,16 +223,16 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
HasContextExtensionSlotBit::encode(scope->HasContextExtensionSlot()) |
IsReplModeScopeBit::encode(scope->is_repl_mode_scope()) |
HasLocalsBlockListBit::encode(false);
scope_info.SetFlags(flags);
scope_info.set_flags(flags);
scope_info.SetParameterCount(parameter_count);
scope_info.SetContextLocalCount(context_local_count);
scope_info.set_parameter_count(parameter_count);
scope_info.set_context_local_count(context_local_count);
// Add context locals' names and info, module variables' names and info.
// Context locals are added using their index.
int context_local_base = index;
int context_local_info_base = context_local_base + context_local_count;
int module_var_entry = scope_info.ModuleVariablesIndex();
int module_var_entry = scope_info.ModuleVariableCountIndex() + 1;
for (Variable* var : *scope->locals()) {
switch (var->location()) {
@ -237,11 +244,11 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
DCHECK_LE(0, local_index);
DCHECK_LT(local_index, context_local_count);
uint32_t info =
VariableModeField::encode(var->mode()) |
InitFlagField::encode(var->initialization_flag()) |
MaybeAssignedFlagField::encode(var->maybe_assigned()) |
ParameterNumberField::encode(ParameterNumberField::kMax) |
IsStaticFlagField::encode(var->is_static_flag());
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(context_local_base + local_index, *var->name(), mode);
scope_info.set(context_local_info_base + local_index,
Smi::FromInt(info));
@ -253,11 +260,11 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
scope_info.set(module_var_entry + kModuleVariableIndexOffset,
Smi::FromInt(var->index()));
uint32_t properties =
VariableModeField::encode(var->mode()) |
InitFlagField::encode(var->initialization_flag()) |
MaybeAssignedFlagField::encode(var->maybe_assigned()) |
ParameterNumberField::encode(ParameterNumberField::kMax) |
IsStaticFlagField::encode(var->is_static_flag());
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));
module_var_entry += kModuleVariableEntryLength;
@ -282,7 +289,7 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
int index = parameter->index() - scope->ContextHeaderLength();
int info_index = context_local_info_base + index;
int info = Smi::ToInt(scope_info.get(info_index));
info = ParameterNumberField::update(info, i);
info = ParameterNumberBits::update(info, i);
scope_info.set(info_index, Smi::FromInt(info));
}
@ -292,11 +299,11 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
if (var->location() == VariableLocation::CONTEXT) {
int local_index = var->index() - scope->ContextHeaderLength();
uint32_t info =
VariableModeField::encode(var->mode()) |
InitFlagField::encode(var->initialization_flag()) |
MaybeAssignedFlagField::encode(var->maybe_assigned()) |
ParameterNumberField::encode(ParameterNumberField::kMax) |
IsStaticFlagField::encode(var->is_static_flag());
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(context_local_base + local_index, *var->name(), mode);
scope_info.set(context_local_info_base + local_index,
Smi::FromInt(info));
@ -358,19 +365,17 @@ Handle<ScopeInfo> ScopeInfo::Create(LocalIsolate* isolate, Zone* zone,
if (has_outer_scope_info) {
scope_info.set(index++, *outer_scope.ToHandleChecked(), mode);
}
}
// Module-specific information (only for module scopes).
if (scope->is_module_scope()) {
Handle<SourceTextModuleInfo> module_info = SourceTextModuleInfo::New(
isolate, zone, scope->AsModuleScope()->module());
DCHECK_EQ(index, scope_info_handle->ModuleInfoIndex());
scope_info_handle->set(index++, *module_info);
DCHECK_EQ(index, scope_info_handle->ModuleVariableCountIndex());
scope_info_handle->set(index++, Smi::FromInt(module_vars_count));
DCHECK_EQ(index, scope_info_handle->ModuleVariablesIndex());
// The variable entries themselves have already been written above.
index += kModuleVariableEntryLength * module_vars_count;
// Module-specific information (only for module scopes).
if (scope->is_module_scope()) {
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));
DCHECK_EQ(index, scope_info.ModuleVariablesIndex());
// The variable entries themselves have already been written above.
index += kModuleVariableEntryLength * module_vars_count;
}
}
DCHECK_EQ(index, scope_info_handle->length());
@ -416,10 +421,10 @@ Handle<ScopeInfo> ScopeInfo::CreateForWithScope(
PrivateNameLookupSkipsOuterClassBit::encode(false) |
HasContextExtensionSlotBit::encode(true) |
IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false);
scope_info->SetFlags(flags);
scope_info->set_flags(flags);
scope_info->SetParameterCount(0);
scope_info->SetContextLocalCount(0);
scope_info->set_parameter_count(0);
scope_info->set_context_local_count(0);
int index = kVariablePartIndex;
DCHECK_EQ(index, scope_info->ReceiverInfoIndex());
@ -496,9 +501,9 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
PrivateNameLookupSkipsOuterClassBit::encode(false) |
HasContextExtensionSlotBit::encode(is_native_context) |
IsReplModeScopeBit::encode(false) | HasLocalsBlockListBit::encode(false);
scope_info->SetFlags(flags);
scope_info->SetParameterCount(parameter_count);
scope_info->SetContextLocalCount(context_local_count);
scope_info->set_flags(flags);
scope_info->set_parameter_count(parameter_count);
scope_info->set_context_local_count(context_local_count);
int index = kVariablePartIndex;
@ -510,11 +515,11 @@ Handle<ScopeInfo> ScopeInfo::CreateForBootstrapping(Isolate* isolate,
DCHECK_EQ(index, scope_info->ContextLocalInfosIndex());
if (context_local_count > 0) {
const uint32_t value =
VariableModeField::encode(VariableMode::kConst) |
InitFlagField::encode(kCreatedInitialized) |
MaybeAssignedFlagField::encode(kNotAssigned) |
ParameterNumberField::encode(ParameterNumberField::kMax) |
IsStaticFlagField::encode(IsStaticFlag::kNotStatic);
VariableModeBits::encode(VariableMode::kConst) |
InitFlagBit::encode(kCreatedInitialized) |
MaybeAssignedFlagBit::encode(kNotAssigned) |
ParameterNumberBits::encode(ParameterNumberBits::kMax) |
IsStaticFlagBit::encode(IsStaticFlag::kNotStatic);
scope_info->set(index++, Smi::FromInt(value));
}
@ -564,7 +569,7 @@ Handle<ScopeInfo> ScopeInfo::RecreateWithBlockList(
// blocklist field, so {LocalsBlockListIndex} returns the correct value.
scope_info->CopyElements(isolate, 0, *original, 0, kVariablePartIndex,
WriteBarrierMode::UPDATE_WRITE_BARRIER);
scope_info->SetFlags(
scope_info->set_flags(
HasLocalsBlockListBit::update(scope_info->Flags(), true));
// Copy the dynamic part including the provided blocklist:
@ -575,7 +580,7 @@ Handle<ScopeInfo> ScopeInfo::RecreateWithBlockList(
isolate, kVariablePartIndex, *original, kVariablePartIndex,
scope_info->LocalsBlockListIndex() - kVariablePartIndex,
WriteBarrierMode::UPDATE_WRITE_BARRIER);
scope_info->set(scope_info->LocalsBlockListIndex(), *blocklist);
scope_info->set_locals_block_list(0, *blocklist);
scope_info->CopyElements(
isolate, scope_info->LocalsBlockListIndex() + 1, *original,
scope_info->LocalsBlockListIndex(),
@ -700,7 +705,7 @@ void ScopeInfo::SetFunctionName(Object name) {
void ScopeInfo::SetInferredFunctionName(String name) {
DCHECK(HasInferredFunctionName());
set(InferredFunctionNameIndex(), name);
set_inferred_function_name(0, name);
}
bool ScopeInfo::HasOuterScopeInfo() const {
@ -714,7 +719,7 @@ bool ScopeInfo::IsDebugEvaluateScope() const {
void ScopeInfo::SetIsDebugEvaluateScope() {
CHECK(!IsEmpty());
DCHECK_EQ(scope_type(), WITH_SCOPE);
SetFlags(Flags() | IsDebugEvaluateScopeBit::encode(true));
set_flags(Flags() | IsDebugEvaluateScopeBit::encode(true));
}
bool ScopeInfo::PrivateNameLookupSkipsOuterClass() const {
@ -731,7 +736,7 @@ bool ScopeInfo::HasLocalsBlockList() const {
StringSet ScopeInfo::LocalsBlockList() const {
DCHECK(HasLocalsBlockList());
return StringSet::cast(get(LocalsBlockListIndex()));
return StringSet::cast(locals_block_list(0));
}
bool ScopeInfo::HasContext() const { return ContextLength() > 0; }
@ -743,7 +748,7 @@ Object ScopeInfo::FunctionName() const {
Object ScopeInfo::InferredFunctionName() const {
DCHECK(HasInferredFunctionName());
return get(InferredFunctionNameIndex());
return inferred_function_name(0);
}
String ScopeInfo::FunctionDebugName() const {
@ -778,66 +783,47 @@ void ScopeInfo::SetPositionInfo(int start, int end) {
ScopeInfo ScopeInfo::OuterScopeInfo() const {
DCHECK(HasOuterScopeInfo());
return ScopeInfo::cast(get(OuterScopeInfoIndex()));
return ScopeInfo::cast(outer_scope_info(0));
}
SourceTextModuleInfo ScopeInfo::ModuleDescriptorInfo() const {
DCHECK(scope_type() == MODULE_SCOPE);
return SourceTextModuleInfo::cast(get(ModuleInfoIndex()));
return SourceTextModuleInfo::cast(module_info(0));
}
String ScopeInfo::ContextLocalName(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
int info_index = ContextLocalNamesIndex() + var;
return String::cast(get(info_index));
return context_local_names(var);
}
VariableMode ScopeInfo::ContextLocalMode(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
int info_index = ContextLocalInfosIndex() + var;
int value = Smi::ToInt(get(info_index));
return VariableModeField::decode(value);
int value = context_local_infos(var);
return VariableModeBits::decode(value);
}
IsStaticFlag ScopeInfo::ContextLocalIsStaticFlag(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
int info_index = ContextLocalInfosIndex() + var;
int value = Smi::ToInt(get(info_index));
return IsStaticFlagField::decode(value);
int value = context_local_infos(var);
return IsStaticFlagBit::decode(value);
}
InitializationFlag ScopeInfo::ContextLocalInitFlag(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
int info_index = ContextLocalInfosIndex() + var;
int value = Smi::ToInt(get(info_index));
return InitFlagField::decode(value);
int value = context_local_infos(var);
return InitFlagBit::decode(value);
}
bool ScopeInfo::ContextLocalIsParameter(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
int info_index = ContextLocalInfosIndex() + var;
int value = Smi::ToInt(get(info_index));
return ParameterNumberField::decode(value) != ParameterNumberField::kMax;
int value = context_local_infos(var);
return ParameterNumberBits::decode(value) != ParameterNumberBits::kMax;
}
uint32_t ScopeInfo::ContextLocalParameterNumber(int var) const {
DCHECK(ContextLocalIsParameter(var));
int info_index = ContextLocalInfosIndex() + var;
int value = Smi::ToInt(get(info_index));
return ParameterNumberField::decode(value);
int value = context_local_infos(var);
return ParameterNumberBits::decode(value);
}
MaybeAssignedFlag ScopeInfo::ContextLocalMaybeAssignedFlag(int var) const {
DCHECK_LE(0, var);
DCHECK_LT(var, ContextLocalCount());
int info_index = ContextLocalInfosIndex() + var;
int value = Smi::ToInt(get(info_index));
return MaybeAssignedFlagField::decode(value);
int value = context_local_infos(var);
return MaybeAssignedFlagBit::decode(value);
}
// static
@ -860,7 +846,7 @@ int ScopeInfo::ModuleIndex(String name, VariableMode* mode,
DCHECK_NOT_NULL(init_flag);
DCHECK_NOT_NULL(maybe_assigned_flag);
int module_vars_count = Smi::ToInt(get(ModuleVariableCountIndex()));
int module_vars_count = module_variable_count(0);
int entry = ModuleVariablesIndex();
for (int i = 0; i < module_vars_count; ++i) {
String var_name = String::cast(get(entry + kModuleVariableNameOffset));
@ -890,7 +876,7 @@ int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
if (scope_info.IsEmpty()) return -1;
int start = scope_info.ContextLocalNamesIndex();
int end = start + scope_info.ContextLocalCount();
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;
@ -909,7 +895,7 @@ int ScopeInfo::ContextSlotIndex(ScopeInfo scope_info, String name,
int ScopeInfo::SavedClassVariableContextLocalIndex() const {
if (HasSavedClassVariableIndexBit::decode(Flags())) {
int index = Smi::ToInt(get(SavedClassVariableInfoIndex()));
int index = saved_class_variable_info(0);
return index - Context::MIN_CONTEXT_SLOTS;
}
return -1;
@ -918,7 +904,7 @@ int ScopeInfo::SavedClassVariableContextLocalIndex() const {
int ScopeInfo::ReceiverContextSlotIndex() const {
if (ReceiverVariableBits::decode(Flags()) ==
VariableAllocationInfo::CONTEXT) {
return Smi::ToInt(get(ReceiverInfoIndex()));
return receiver_info(0);
}
return -1;
}
@ -938,53 +924,51 @@ FunctionKind ScopeInfo::function_kind() const {
}
int ScopeInfo::ContextLocalNamesIndex() const {
DCHECK_LE(kVariablePartIndex, length());
return kVariablePartIndex;
return ConvertOffsetToIndex(kContextLocalNamesOffset);
}
int ScopeInfo::ContextLocalInfosIndex() const {
return ContextLocalNamesIndex() + ContextLocalCount();
return ConvertOffsetToIndex(ContextLocalInfosOffset());
}
int ScopeInfo::SavedClassVariableInfoIndex() const {
return ContextLocalInfosIndex() + ContextLocalCount();
return ConvertOffsetToIndex(SavedClassVariableInfoOffset());
}
int ScopeInfo::ReceiverInfoIndex() const {
return SavedClassVariableInfoIndex() + (HasSavedClassVariableIndex() ? 1 : 0);
return ConvertOffsetToIndex(ReceiverInfoOffset());
}
int ScopeInfo::FunctionNameInfoIndex() const {
return ReceiverInfoIndex() + (HasAllocatedReceiver() ? 1 : 0);
return ConvertOffsetToIndex(FunctionNameInfoOffset());
}
int ScopeInfo::InferredFunctionNameIndex() const {
return FunctionNameInfoIndex() +
(HasFunctionName() ? kFunctionNameEntries : 0);
return ConvertOffsetToIndex(InferredFunctionNameOffset());
}
int ScopeInfo::PositionInfoIndex() const {
return InferredFunctionNameIndex() + (HasInferredFunctionName() ? 1 : 0);
return ConvertOffsetToIndex(PositionInfoOffset());
}
int ScopeInfo::OuterScopeInfoIndex() const {
return PositionInfoIndex() + (HasPositionInfo() ? kPositionInfoEntries : 0);
return ConvertOffsetToIndex(OuterScopeInfoOffset());
}
int ScopeInfo::LocalsBlockListIndex() const {
return OuterScopeInfoIndex() + (HasOuterScopeInfo() ? 1 : 0);
return ConvertOffsetToIndex(LocalsBlockListOffset());
}
int ScopeInfo::ModuleInfoIndex() const {
return LocalsBlockListIndex() + (HasLocalsBlockList() ? 1 : 0);
return ConvertOffsetToIndex(ModuleInfoOffset());
}
int ScopeInfo::ModuleVariableCountIndex() const {
return ModuleInfoIndex() + 1;
return ConvertOffsetToIndex(ModuleVariableCountOffset());
}
int ScopeInfo::ModuleVariablesIndex() const {
return ModuleVariableCountIndex() + 1;
return ConvertOffsetToIndex(ModuleVariablesOffset());
}
void ScopeInfo::ModuleVariable(int i, String* name, int* index,
@ -992,7 +976,7 @@ void ScopeInfo::ModuleVariable(int i, String* name, int* index,
InitializationFlag* init_flag,
MaybeAssignedFlag* maybe_assigned_flag) {
DCHECK_LE(0, i);
DCHECK_LT(i, Smi::ToInt(get(ModuleVariableCountIndex())));
DCHECK_LT(i, module_variable_count(0));
int entry = ModuleVariablesIndex() + i * kModuleVariableEntryLength;
int properties = Smi::ToInt(get(entry + kModuleVariablePropertiesOffset));
@ -1005,13 +989,13 @@ void ScopeInfo::ModuleVariable(int i, String* name, int* index,
DCHECK_NE(*index, 0);
}
if (mode != nullptr) {
*mode = VariableModeField::decode(properties);
*mode = VariableModeBits::decode(properties);
}
if (init_flag != nullptr) {
*init_flag = InitFlagField::decode(properties);
*init_flag = InitFlagBit::decode(properties);
}
if (maybe_assigned_flag != nullptr) {
*maybe_assigned_flag = MaybeAssignedFlagField::decode(properties);
*maybe_assigned_flag = MaybeAssignedFlagBit::decode(properties);
}
}

View File

@ -19,6 +19,8 @@
namespace v8 {
namespace internal {
#include "torque-generated/src/objects/scope-info-tq.inc"
template <typename T>
class Handle;
class Isolate;
@ -36,12 +38,27 @@ class Zone;
// This object provides quick access to scope info details for runtime
// routines.
class ScopeInfo : public FixedArray {
class ScopeInfo : public TorqueGeneratedScopeInfo<ScopeInfo, FixedArrayBase> {
public:
DEFINE_TORQUE_GENERATED_SCOPE_FLAGS()
DECL_CAST(ScopeInfo)
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);
using BodyDescriptor = FlexibleBodyDescriptor<kHeaderSize>;
// Return the type of this scope.
ScopeType scope_type() const;
@ -238,19 +255,12 @@ class ScopeInfo : public FixedArray {
// Serializes empty scope info.
V8_EXPORT_PRIVATE static ScopeInfo Empty(Isolate* isolate);
// The layout of the static part of a ScopeInfo is as follows. Each entry is
// numeric and occupies one array slot.
// 1. A set of properties of the scope.
// 2. The number of parameters. For non-function scopes this is 0.
// 3. The number of non-parameter and parameter variables allocated in the
// context.
#define FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(V) \
V(Flags) \
V(ParameterCount) \
V(ContextLocalCount)
#define FIELD_ACCESSORS(name) \
inline void Set##name(int value); \
inline int name() const;
FOR_EACH_SCOPE_INFO_NUMERIC_FIELD(FIELD_ACCESSORS)
#undef FIELD_ACCESSORS
@ -262,7 +272,11 @@ class ScopeInfo : public FixedArray {
kVariablePartIndex
};
static const int kFlagsOffset = OffsetOfElementAt(Fields::kFlags);
// 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);
@ -270,44 +284,6 @@ class ScopeInfo : public FixedArray {
bool IsEmpty() const;
private:
// The layout of the variable part of a ScopeInfo is as follows:
// 1. ContextLocalNames:
// Contains the names of local variables and parameters that are allocated
// in the context. They are stored in increasing order of the context slot
// index starting with Context::MIN_CONTEXT_SLOTS. One slot is used per
// context local, so in total this part occupies ContextLocalCount() slots
// in the array.
// 2. ContextLocalInfos:
// Contains the variable modes and initialization flags corresponding to
// the context locals in ContextLocalNames. One slot is used per
// context local, so in total this part occupies ContextLocalCount()
// slots in the array.
// 3. SavedClassVariableInfo:
// If the scope is a class scope and it has static private methods that
// may be accessed directly or through eval, one slot is reserved to hold
// the context slot index for the class variable.
// 4. ReceiverInfo:
// If the scope binds a "this" value, one slot is reserved to hold the
// context or stack slot index for the variable.
// 5. FunctionNameInfo:
// If the scope belongs to a named function expression this part contains
// information about the function variable. It always occupies two array
// slots: a. The name of the function variable.
// b. The context or stack slot index for the variable.
// 6. InferredFunctionName:
// Contains the function's inferred name.
// 7. SourcePosition:
// Contains two slots with a) the startPosition and b) the endPosition if
// the scope belongs to a function or script.
// 8. OuterScopeInfoIndex:
// The outer scope's ScopeInfo or the hole if there's none.
// 9. LocalsBlockList: List of stack allocated local variables. Used by
// debug evaluate to properly abort variable lookup when a name clashes
// with a stack allocated local that can't be materialized.
// 10. SourceTextModuleInfo, ModuleVariableCount, and ModuleVariables:
// For a module scope, this part contains the SourceTextModuleInfo, the
// number of MODULE-allocated variables, and the metadata of those
// variables. For non-module scopes it is empty.
int ContextLocalNamesIndex() const;
int ContextLocalInfosIndex() const;
int SavedClassVariableInfoIndex() const;
@ -323,6 +299,13 @@ class ScopeInfo : public FixedArray {
static bool NeedsPositionInfo(ScopeType type);
// Converts byte offsets within the object to FixedArray-style indices.
static constexpr int ConvertOffsetToIndex(int offset) {
int index = (offset - FixedArray::kHeaderSize) / kTaggedSize;
CONSTEXPR_DCHECK(FixedArray::OffsetOfElementAt(index) == offset);
return index;
}
enum class BootstrappingType { kScript, kFunction, kNative };
static Handle<ScopeInfo> CreateForBootstrapping(Isolate* isolate,
BootstrappingType type);
@ -342,21 +325,13 @@ class ScopeInfo : public FixedArray {
static const int kFunctionNameEntries = 2;
static const int kPositionInfoEntries = 2;
// Hide an inherited member function to ensure that callers have been updated
// to use IsEmpty instead.
using FixedArray::length;
// Properties of variables.
using VariableModeField = base::BitField<VariableMode, 0, 4>;
using InitFlagField = VariableModeField::Next<InitializationFlag, 1>;
using MaybeAssignedFlagField = InitFlagField::Next<MaybeAssignedFlag, 1>;
using ParameterNumberField = MaybeAssignedFlagField::Next<uint32_t, 16>;
using IsStaticFlagField = ParameterNumberField::Next<IsStaticFlag, 1>;
DEFINE_TORQUE_GENERATED_VARIABLE_PROPERTIES()
friend class ScopeIterator;
friend std::ostream& operator<<(std::ostream& os, VariableAllocationInfo var);
OBJECT_CONSTRUCTORS(ScopeInfo, FixedArray);
TQ_OBJECT_CONSTRUCTORS(ScopeInfo)
FRIEND_TEST(TestWithNativeContext, RecreateScopeInfoWithLocalsBlocklistWorks);
};

View File

@ -2,23 +2,49 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
extern class ScopeInfo extends FixedArray;
extern macro EmptyScopeInfoConstant(): ScopeInfo;
const kEmptyScopeInfo: ScopeInfo = EmptyScopeInfoConstant();
const kScopeInfoFlagsIndex:
constexpr int32 generates 'ScopeInfo::Fields::kFlags';
operator '.flags' macro LoadScopeInfoFlags(implicit context: Context)(
scopeInfo: ScopeInfo): ScopeFlags {
return Convert<ScopeFlags>(
UnsafeCast<Smi>(scopeInfo.objects[kScopeInfoFlagsIndex]));
extern enum ScopeType extends uint32 {
CLASS_SCOPE, // Also used for the empty scope (for NativeContext & builtins).
EVAL_SCOPE,
FUNCTION_SCOPE,
MODULE_SCOPE,
SCRIPT_SCOPE,
CATCH_SCOPE,
BLOCK_SCOPE,
WITH_SCOPE
}
type ScopeType extends uint32 constexpr 'ScopeType';
type VariableAllocationInfo extends uint32
constexpr 'VariableAllocationInfo';
extern enum VariableAllocationInfo extends uint32 {
NONE,
STACK,
CONTEXT,
UNUSED
}
extern enum VariableMode extends uint32 {
kLet,
kConst,
kVar,
kTemporary,
kDynamic,
kDynamicGlobal,
kDynamicLocal,
kPrivateMethod,
kPrivateSetterOnly,
kPrivateGetterOnly,
kPrivateGetterAndSetter
}
extern enum InitializationFlag extends uint32 {
kNeedsInitialization,
kCreatedInitialized
}
extern enum IsStaticFlag extends uint32 { kNotStatic, kStatic }
extern enum MaybeAssignedFlag extends uint32 { kNotAssigned, kMaybeAssigned }
// Properties of scopes.
bitfield struct ScopeFlags extends uint31 {
@ -46,3 +72,97 @@ bitfield struct ScopeFlags extends uint31 {
has_locals_block_list: bool: 1 bit;
is_empty: bool: 1 bit;
}
struct PositionInfo {
start: Smi;
end: Smi;
}
struct FunctionNameInfo {
function_variable_name: String|Zero;
function_variable_context_or_stack_slot_index: Smi;
}
bitfield struct VariableProperties extends uint31 {
variable_mode: VariableMode: 4 bit;
init_flag: InitializationFlag: 1 bit;
maybe_assigned_flag: MaybeAssignedFlag: 1 bit;
parameter_number: uint32: 16 bit;
is_static_flag: IsStaticFlag: 1 bit;
}
struct ModuleVariable {
name: String;
index: Smi;
properties: SmiTagged<VariableProperties>;
}
@generateCppClass
extern class ScopeInfo extends FixedArrayBase {
const flags: SmiTagged<ScopeFlags>;
// The number of parameters. For non-function scopes this is 0.
parameter_count: Smi;
// The number of non-parameter and parameter variables allocated in the
// context.
const context_local_count: Smi;
// Contains the names of local variables and parameters that are allocated
// in the context. They are stored in increasing order of the context slot
// index starting with Context::MIN_CONTEXT_SLOTS.
context_local_names[context_local_count]: String;
// Contains the variable modes and initialization flags corresponding to
// the context locals in ContextLocalNames.
context_local_infos[context_local_count]: SmiTagged<VariableProperties>;
// If the scope is a class scope and it has static private methods that
// may be accessed directly or through eval, one slot is reserved to hold
// the context slot index for the class variable.
saved_class_variable_info[flags.has_saved_class_variable_index ? 1 : 0]: Smi;
// If the scope binds a "this" value, one slot is reserved to hold the
// context or stack slot index for the variable.
receiver_info[
flags.receiver_variable ==
FromConstexpr<VariableAllocationInfo>(VariableAllocationInfo::STACK)
|| flags.receiver_variable ==
FromConstexpr<VariableAllocationInfo>(VariableAllocationInfo::CONTEXT)
? 1 : 0]: Smi;
// If the scope belongs to a named function expression this part contains
// information about the function variable. It always occupies two array
// slots: a. The name of the function variable.
// b. The context or stack slot index for the variable.
function_name_info[flags.function_variable != FromConstexpr<VariableAllocationInfo>(VariableAllocationInfo::NONE) ? 1 : 0]:
FunctionNameInfo;
inferred_function_name[flags.has_inferred_function_name ? 1 : 0]: String|
Undefined;
// Contains two slots with a) the startPosition and b) the endPosition if
// the scope belongs to a function or script.
position_info[flags.scope_type == ScopeType::FUNCTION_SCOPE ||
flags.scope_type == ScopeType::SCRIPT_SCOPE ||
flags.scope_type == ScopeType::EVAL_SCOPE ||
flags.scope_type == ScopeType::MODULE_SCOPE
? 1 : 0]: PositionInfo;
outer_scope_info[flags.has_outer_scope_info ? 1 : 0]: ScopeInfo|TheHole;
// List of stack allocated local variables. Used by debug evaluate to properly
// abort variable lookup when a name clashes with a stack allocated local that
// can't be materialized.
locals_block_list[flags.has_locals_block_list ? 1 : 0]: HashTable;
// For a module scope, this part contains the SourceTextModuleInfo, the
// number of MODULE-allocated variables, and the metadata of those
// variables. For non-module scopes it is empty.
module_info[flags.scope_type == ScopeType::MODULE_SCOPE ? 1 : 0]:
SourceTextModuleInfo;
const module_variable_count[flags.scope_type == ScopeType::MODULE_SCOPE ? 1 : 0]:
Smi;
module_variables[flags.scope_type == ScopeType::MODULE_SCOPE ? module_variable_count[0] : 0]:
ModuleVariable;
}

View File

@ -636,7 +636,7 @@ HeapEntry* V8HeapExplorer::AddEntry(HeapObject object) {
} else if (object.IsContext()) {
return AddEntry(object, HeapEntry::kObject, "system / Context");
} else if (object.IsFixedArray() || object.IsFixedDoubleArray() ||
object.IsByteArray()) {
object.IsByteArray() || object.IsScopeInfo()) {
return AddEntry(object, HeapEntry::kArray, "");
} else if (object.IsHeapNumber()) {
return AddEntry(object, HeapEntry::kHeapNumber, "number");

View File

@ -21,22 +21,6 @@ base::Optional<Stack<std::string>> CCGenerator::EmitGraph(
parameters.Peek(i));
}
// C++ doesn't have parameterized labels like CSA, so we must pre-declare all
// phi values so they're in scope for both the blocks that define them and the
// blocks that read them.
for (Block* block : cfg_.blocks()) {
if (block->IsDead()) continue;
DCHECK_EQ(block->InputTypes().Size(), block->InputDefinitions().Size());
for (BottomOffset i = {0}; i < block->InputTypes().AboveTop(); ++i) {
DefinitionLocation input_def = block->InputDefinitions().Peek(i);
if (block->InputDefinitions().Peek(i).IsPhiFromBlock(block)) {
out() << " " << block->InputTypes().Peek(i)->GetRuntimeType() << " "
<< DefinitionToVariable(input_def) << ";\n";
}
}
}
// Redirect the output of non-declarations into a buffer and only output
// declarations right away.
std::stringstream out_buffer;
@ -198,7 +182,16 @@ void CCGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
if (return_type->IsConstexpr()) {
ReportError("%FromConstexpr must return a non-constexpr type");
}
// Nothing to do here; constexpr expressions are already valid C++.
if (return_type->IsSubtypeOf(TypeOracle::GetSmiType())) {
if (is_cc_debug_) {
out() << "Internals::IntToSmi";
} else {
out() << "Smi::FromInt";
}
}
// Wrap the raw constexpr value in a static_cast to ensure that
// enums get properly casted to their backing integral value.
out() << "(CastToUnderlyingTypeIfEnum";
} else {
ReportError("no built in intrinsic with name " +
instruction.intrinsic->ExternalName());
@ -206,6 +199,9 @@ void CCGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
out() << "(";
PrintCommaSeparatedList(out(), args);
if (instruction.intrinsic->ExternalName() == "%FromConstexpr") {
out() << ")";
}
out() << ");\n";
}
@ -247,10 +243,10 @@ void CCGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
if (is_cc_debug_) {
out() << instruction.macro->CCDebugName() << "(accessor";
if (!args.empty()) out() << ", ";
} else {
out() << instruction.macro->CCName() << "(isolate";
out() << instruction.macro->CCName() << "(";
}
if (!args.empty()) out() << ", ";
PrintCommaSeparatedList(out(), args);
if (is_cc_debug_) {
out() << "));\n";
@ -384,8 +380,23 @@ void CCGenerator::EmitInstruction(const LoadReferenceInstruction& instruction,
<< result_name << ");\n";
out() << " " << result_name << " = ";
if (instruction.type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
out() << "TaggedField<" << result_type << ">::load(isolate, " << object
<< ", static_cast<int>(" << offset << "));\n";
// Currently, all of the tagged loads we emit are for smi values, so there
// is no point in providing an IsolateRoot. If at some point we start
// emitting loads for tagged fields which might be HeapObjects, then we
// should plumb an IsolateRoot through the generated functions that need
// it.
if (!instruction.type->IsSubtypeOf(TypeOracle::GetSmiType())) {
Error(
"Not supported in C++ output: LoadReference on non-smi tagged "
"value");
}
// References and slices can cause some values to have the Torque type
// HeapObject|TaggedZeroPattern, which is output as "Object". TaggedField
// requires HeapObject, so we need a cast.
out() << "TaggedField<" << result_type
<< ">::load(*static_cast<HeapObject*>(&" << object
<< "), static_cast<int>(" << offset << "));\n";
} else {
out() << "(" << object << ").ReadField<" << result_type << ">(" << offset
<< ");\n";
@ -438,13 +449,17 @@ void CCGenerator::EmitInstruction(const LoadBitFieldInstruction& instruction,
Type::MatchUnaryGeneric(struct_type, TypeOracle::GetSmiTaggedGeneric());
if (smi_tagged_type) {
// Get the untagged value and its type.
bit_field_struct = bit_field_struct + ".value()";
if (is_cc_debug_) {
bit_field_struct = "Internals::SmiValue(" + bit_field_struct + ")";
} else {
bit_field_struct = bit_field_struct + ".value()";
}
struct_type = *smi_tagged_type;
}
out() << " " << result_name << " = "
out() << " " << result_name << " = CastToUnderlyingTypeIfEnum("
<< GetBitFieldSpecialization(struct_type, instruction.bit_field)
<< "::decode(" << bit_field_struct << ");\n";
<< "::decode(" << bit_field_struct << "));\n";
}
void CCGenerator::EmitInstruction(const StoreBitFieldInstruction& instruction,

View File

@ -33,6 +33,15 @@ std::vector<T*> FilterDeclarables(const std::vector<Declarable*> list) {
return result;
}
inline std::string UnwrapTNodeTypeName(const std::string& generates) {
if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
generates.substr(generates.length() - 1, 1) != ">") {
ReportError("generated type \"", generates,
"\" should be of the form \"TNode<...>\"");
}
return generates.substr(6, generates.length() - 7);
}
class Declarations {
public:
static std::vector<Declarable*> TryLookup(const QualifiedName& name) {

View File

@ -1774,13 +1774,10 @@ std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration(
o << " " << macro_prefix << name << "(";
bool first = true;
if (output_type_ == OutputType::kCC) {
first = false;
o << "Isolate* isolate";
} else if (output_type_ == OutputType::kCCDebug) {
if (output_type_ == OutputType::kCCDebug) {
first = false;
o << "d::MemoryAccessor accessor";
} else if (pass_code_assembler_state) {
} else if (output_type_ == OutputType::kCSA && pass_code_assembler_state) {
first = false;
o << "compiler::CodeAssemblerState* state_";
}
@ -3459,6 +3456,7 @@ class FieldOffsetsGenerator {
explicit FieldOffsetsGenerator(const ClassType* type) : type_(type) {}
virtual void WriteField(const Field& f, const std::string& size_string) = 0;
virtual void WriteFieldOffsetGetter(const Field& f) = 0;
virtual void WriteMarker(const std::string& marker) = 0;
virtual ~FieldOffsetsGenerator() { CHECK(is_finished_); }
@ -3480,7 +3478,11 @@ class FieldOffsetsGenerator {
size_t field_size;
std::tie(field_size, size_string) = f.GetFieldSizeInformation();
}
WriteField(f, size_string);
if (f.offset.has_value()) {
WriteField(f, size_string);
} else {
WriteFieldOffsetGetter(f);
}
}
void Finish() {
@ -3586,6 +3588,9 @@ class MacroFieldOffsetsGenerator : public FieldOffsetsGenerator {
out_ << "V(k" << CamelifyString(f.name_and_type.name) << "Offset, "
<< size_string << ") \\\n";
}
void WriteFieldOffsetGetter(const Field& f) override {
// Can't do anything here.
}
void WriteMarker(const std::string& marker) override {
out_ << "V(" << marker << ", 0) \\\n";
}
@ -3713,10 +3718,13 @@ namespace {
class ClassFieldOffsetGenerator : public FieldOffsetsGenerator {
public:
ClassFieldOffsetGenerator(std::ostream& header, const ClassType* type)
ClassFieldOffsetGenerator(std::ostream& header, std::ostream& inline_header,
const ClassType* type, std::string gen_name_T)
: FieldOffsetsGenerator(type),
hdr_(header),
previous_field_end_("P::kHeaderSize") {}
inl_(inline_header),
previous_field_end_("P::kHeaderSize"),
gen_name_T_(gen_name_T) {}
void WriteField(const Field& f, const std::string& size_string) override {
std::string field = "k" + CamelifyString(f.name_and_type.name) + "Offset";
std::string field_end = field + "End";
@ -3726,6 +3734,22 @@ class ClassFieldOffsetGenerator : public FieldOffsetsGenerator {
<< size_string << " - 1;\n";
previous_field_end_ = field_end + " + 1";
}
void WriteFieldOffsetGetter(const Field& f) override {
// A static constexpr int is more convenient than a getter if the offset is
// known.
DCHECK(!f.offset.has_value());
std::string function_name = CamelifyString(f.name_and_type.name) + "Offset";
hdr_ << " inline int " << function_name << "() const;\n";
inl_ << "template <class D, class P>\n";
inl_ << "int " << gen_name_T_ << "::" << function_name << "() const {\n";
// Item 1 in a flattened slice is the offset.
inl_ << " return static_cast<int>(std::get<1>("
<< Callable::PrefixNameForCCOutput(type_->GetSliceMacroName(f))
<< "(*static_cast<const D*>(this))));\n";
inl_ << "}\n\n";
}
void WriteMarker(const std::string& marker) override {
hdr_ << " static constexpr int " << marker << " = " << previous_field_end_
<< ";\n";
@ -3733,7 +3757,9 @@ class ClassFieldOffsetGenerator : public FieldOffsetsGenerator {
private:
std::ostream& hdr_;
std::ostream& inl_;
std::string previous_field_end_;
std::string gen_name_T_;
};
class CppClassGenerator {
@ -3764,6 +3790,8 @@ class CppClassGenerator {
void GenerateClassCasts();
std::string GetFieldOffsetForAccessor(const Field& f);
const ClassType* type_;
const ClassType* super_;
const std::string name_;
@ -3852,7 +3880,7 @@ void CppClassGenerator::GenerateClass() {
}
hdr_ << "\n";
ClassFieldOffsetGenerator g(hdr_, type_);
ClassFieldOffsetGenerator g(hdr_, inl_, type_, gen_name_T_);
for (auto f : type_->fields()) {
CurrentSourcePosition::Scope scope(f.pos);
g.RecordOffsetFor(f);
@ -3865,6 +3893,21 @@ void CppClassGenerator::GenerateClass() {
if (!index_fields.has_value()) {
hdr_ << " // SizeFor implementations not generated due to complex array "
"lengths\n\n";
const Field& last_field = type_->LastField();
std::string last_field_item_size =
std::get<1>(*SizeOf(last_field.name_and_type.type));
hdr_ << " inline int AllocatedSize();\n\n";
inl_ << "template <class D, class P>\n";
inl_ << "int " << gen_name_T_ << "::AllocatedSize() {\n";
inl_ << " auto slice = "
<< Callable::PrefixNameForCCOutput(
type_->GetSliceMacroName(last_field))
<< "(*static_cast<const D*>(this));\n";
inl_ << " return static_cast<int>(std::get<1>(slice)) + "
<< last_field_item_size
<< " * static_cast<int>(std::get<2>(slice));\n";
inl_ << "}\n\n";
} else if (type_->ShouldGenerateBodyDescriptor() ||
(!type_->IsAbstract() &&
!type_->IsSubtypeOf(TypeOracle::GetJSObjectType()))) {
@ -4001,11 +4044,18 @@ std::string GenerateRuntimeTypeCheck(const Type* type,
void GenerateBoundsDCheck(std::ostream& os, const std::string& index,
const ClassType* type, const Field& f) {
os << " DCHECK_GE(" << index << ", 0);\n";
std::string length_expression;
if (base::Optional<NameAndType> array_length =
ExtractSimpleFieldArraySize(*type, *f.index)) {
os << " DCHECK_LT(" << index << ", this->" << array_length->name
<< "());\n";
length_expression = "this ->" + array_length->name + "()";
} else {
// The length is element 2 in the flattened field slice.
length_expression =
"static_cast<int>(std::get<2>(" +
Callable::PrefixNameForCCOutput(type->GetSliceMacroName(f)) +
"(*static_cast<const D*>(this))))";
}
os << " DCHECK_LT(" << index << ", " << length_expression << ");\n";
}
} // namespace
@ -4038,6 +4088,13 @@ void CppClassGenerator::GenerateFieldAccessor(const Field& f) {
.Position(f.pos);
}
std::string CppClassGenerator::GetFieldOffsetForAccessor(const Field& f) {
if (f.offset.has_value()) {
return "k" + CamelifyString(f.name_and_type.name) + "Offset";
}
return CamelifyString(f.name_and_type.name) + "Offset()";
}
void CppClassGenerator::GenerateFieldAccessorForUntagged(const Field& f) {
DCHECK(!f.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType()));
const Type* field_type = f.name_and_type.type;
@ -4053,7 +4110,7 @@ void CppClassGenerator::GenerateFieldAccessorForUntagged(const Field& f) {
}
const std::string& name = f.name_and_type.name;
const std::string type = constexpr_version->GetGeneratedTypeName();
std::string offset = "k" + CamelifyString(name) + "Offset";
std::string offset = GetFieldOffsetForAccessor(f);
// Generate declarations in header.
if (f.index) {
@ -4110,7 +4167,7 @@ void CppClassGenerator::GenerateFieldAccessorForSmi(const Field& f) {
// Follow the convention to create Smi accessors with type int.
const std::string type = "int";
const std::string& name = f.name_and_type.name;
const std::string offset = "k" + CamelifyString(name) + "Offset";
const std::string offset = GetFieldOffsetForAccessor(f);
// Generate declarations in header.
if (f.index) {
@ -4131,7 +4188,7 @@ void CppClassGenerator::GenerateFieldAccessorForSmi(const Field& f) {
if (f.index) {
GenerateBoundsDCheck(inl_, "i", type_, f);
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " return this->template ReadField<Smi>(offset).value();\n";
inl_ << " return TaggedField<Smi>::load(*this, offset).value();\n";
inl_ << "}\n";
} else {
inl_ << " return TaggedField<Smi, " << offset
@ -4162,7 +4219,7 @@ void CppClassGenerator::GenerateFieldAccessorForTagged(const Field& f) {
const Type* field_type = f.name_and_type.type;
DCHECK(field_type->IsSubtypeOf(TypeOracle::GetTaggedType()));
const std::string& name = f.name_and_type.name;
std::string offset = "k" + CamelifyString(name) + "Offset";
std::string offset = GetFieldOffsetForAccessor(f);
bool strong_pointer = field_type->IsSubtypeOf(TypeOracle::GetObjectType());
std::string type = field_type->UnhandlifiedCppTypeName();
@ -4710,7 +4767,7 @@ void GenerateClassFieldVerifier(const std::string& class_name,
<< length << ") = "
<< Callable::PrefixNameForCCOutput(
class_type.GetSliceMacroName(f))
<< "(isolate, o);\n";
<< "(o);\n";
// Slices use intptr, but TaggedField<T>.load() uses int, so verify that
// such a cast is valid.

View File

@ -13,26 +13,26 @@
namespace v8 {
namespace internal {
class Isolate;
namespace TorqueRuntimeMacroShims {
namespace CodeStubAssembler {
inline intptr_t ChangeInt32ToIntPtr(Isolate* isolate, int32_t i) { return i; }
inline uintptr_t ChangeUint32ToWord(Isolate* isolate, uint32_t u) { return u; }
inline intptr_t IntPtrAdd(Isolate* isolate, intptr_t a, intptr_t b) {
return a + b;
}
inline intptr_t IntPtrMul(Isolate* isolate, intptr_t a, intptr_t b) {
return a * b;
}
inline intptr_t Signed(Isolate* isolate, uintptr_t u) {
return static_cast<intptr_t>(u);
}
inline bool BoolConstant(bool b) { return b; }
inline intptr_t ChangeInt32ToIntPtr(int32_t i) { return i; }
inline uintptr_t ChangeUint32ToWord(uint32_t u) { return u; }
inline intptr_t IntPtrAdd(intptr_t a, intptr_t b) { return a + b; }
inline intptr_t IntPtrMul(intptr_t a, intptr_t b) { return a * b; }
inline intptr_t Signed(uintptr_t u) { return static_cast<intptr_t>(u); }
template <typename Smi>
inline int32_t SmiUntag(Isolate* isolate, Smi s) {
inline int32_t SmiUntag(Smi s) {
return s.value();
}
inline bool UintPtrLessThan(uintptr_t a, uintptr_t b) { return a < b; }
inline uint32_t Unsigned(int32_t s) { return static_cast<uint32_t>(s); }
#if V8_HOST_ARCH_64_BIT
inline uintptr_t Unsigned(intptr_t s) { return static_cast<uintptr_t>(s); }
#endif
inline bool Word32Equal(uint32_t a, uint32_t b) { return a == b; }
inline bool Word32NotEqual(uint32_t a, uint32_t b) { return a != b; }
} // namespace CodeStubAssembler
} // namespace TorqueRuntimeMacroShims

View File

@ -983,7 +983,7 @@ base::Optional<ParseResult> MakeClassDeclaration(
std::vector<Declaration*> result;
result.push_back(MakeNode<ClassDeclaration>(
name, flags, extends, std::move(generates), std::move(methods), fields,
name, flags, extends, generates, std::move(methods), fields,
MakeInstanceTypeConstraints(annotations)));
Identifier* constexpr_name =
@ -993,7 +993,8 @@ base::Optional<ParseResult> MakeClassDeclaration(
AbstractTypeFlags abstract_type_flags(AbstractTypeFlag::kConstexpr);
if (transient) abstract_type_flags |= AbstractTypeFlag::kTransient;
TypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>(
constexpr_name, abstract_type_flags, constexpr_extends, name->value);
constexpr_name, abstract_type_flags, constexpr_extends,
generates ? UnwrapTNodeTypeName(*generates) : name->value);
constexpr_decl->pos = name->pos;
result.push_back(constexpr_decl);

View File

@ -63,12 +63,7 @@ std::string ComputeGeneratesType(base::Optional<std::string> opt_gen,
if (!opt_gen) return "";
const std::string& generates = *opt_gen;
if (enforce_tnode_type) {
if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
generates.substr(generates.length() - 1, 1) != ">") {
ReportError("generated type \"", generates,
"\" should be of the form \"TNode<...>\"");
}
return generates.substr(6, generates.length() - 7);
return UnwrapTNodeTypeName(generates);
}
return generates;
}

View File

@ -576,6 +576,16 @@ class AggregateType : public Type {
return {{name_, ""}};
}
const Field& LastField() const {
for (base::Optional<const AggregateType*> current = this;
current.has_value();
current = (*current)->parent()->AggregateSupertype()) {
const std::vector<Field>& fields = (*current)->fields_;
if (!fields.empty()) return fields[fields.size() - 1];
}
ReportError("Can't get last field of empty aggregate type");
}
protected:
AggregateType(Kind kind, const Type* parent, Namespace* nspace,
const std::string& name,

View File

@ -446,7 +446,13 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.Return();
// Generate BytecodeArray.
scope.SetScriptScopeInfo(factory->NewScopeInfo(1));
Handle<ScopeInfo> scope_info =
factory->NewScopeInfo(ScopeInfo::kVariablePartIndex);
scope_info->set_flags(0);
scope_info->set_context_local_count(0);
scope_info->set_parameter_count(0);
scope.SetScriptScopeInfo(scope_info);
ast_factory.Internalize(isolate());
Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate());
CHECK_EQ(the_array->frame_size(),

View File

@ -47,6 +47,9 @@ namespace debug_helper_internal {
namespace TorqueDebugMacroShims {
namespace CodeStubAssembler {
inline Value<bool> BoolConstant(d::MemoryAccessor accessor, bool b) {
return {d::MemoryAccessResult::kOk, b};
}
inline Value<intptr_t> ChangeInt32ToIntPtr(d::MemoryAccessor accessor,
int32_t i) {
return {d::MemoryAccessResult::kOk, i};
@ -70,6 +73,26 @@ inline Value<int32_t> SmiUntag(d::MemoryAccessor accessor, uintptr_t s_t) {
Smi s(s_t);
return {d::MemoryAccessResult::kOk, s.value()};
}
inline Value<bool> UintPtrLessThan(d::MemoryAccessor accessor, uintptr_t a,
uintptr_t b) {
return {d::MemoryAccessResult::kOk, a < b};
}
inline Value<uint32_t> Unsigned(d::MemoryAccessor accessor, int32_t s) {
return {d::MemoryAccessResult::kOk, static_cast<uint32_t>(s)};
}
#if V8_HOST_ARCH_64_BIT
inline Value<uintptr_t> Unsigned(d::MemoryAccessor accessor, intptr_t s) {
return {d::MemoryAccessResult::kOk, static_cast<uintptr_t>(s)};
}
#endif
inline Value<bool> Word32Equal(d::MemoryAccessor accessor, uint32_t a,
uint32_t b) {
return {d::MemoryAccessResult::kOk, a == b};
}
inline Value<bool> Word32NotEqual(d::MemoryAccessor accessor, uint32_t a,
uint32_t b) {
return {d::MemoryAccessResult::kOk, a != b};
}
} // namespace CodeStubAssembler
} // namespace TorqueDebugMacroShims

View File

@ -89,12 +89,12 @@ INSTANCE_TYPES = {
125: "SIMPLE_NUMBER_DICTIONARY_TYPE",
126: "CLOSURE_FEEDBACK_CELL_ARRAY_TYPE",
127: "OBJECT_BOILERPLATE_DESCRIPTION_TYPE",
128: "SCOPE_INFO_TYPE",
129: "SCRIPT_CONTEXT_TABLE_TYPE",
130: "BYTE_ARRAY_TYPE",
131: "BYTECODE_ARRAY_TYPE",
132: "FIXED_DOUBLE_ARRAY_TYPE",
133: "INTERNAL_CLASS_WITH_SMI_ELEMENTS_TYPE",
128: "SCRIPT_CONTEXT_TABLE_TYPE",
129: "BYTE_ARRAY_TYPE",
130: "BYTECODE_ARRAY_TYPE",
131: "FIXED_DOUBLE_ARRAY_TYPE",
132: "INTERNAL_CLASS_WITH_SMI_ELEMENTS_TYPE",
133: "SCOPE_INFO_TYPE",
134: "SLOPPY_ARGUMENTS_ELEMENTS_TYPE",
135: "AWAIT_CONTEXT_TYPE",
136: "BLOCK_CONTEXT_TYPE",
@ -245,12 +245,12 @@ KNOWN_MAPS = {
("read_only_space", 0x023cd): (66, "HeapNumberMap"),
("read_only_space", 0x02401): (67, "TheHoleMap"),
("read_only_space", 0x02461): (67, "BooleanMap"),
("read_only_space", 0x02505): (130, "ByteArrayMap"),
("read_only_space", 0x02505): (129, "ByteArrayMap"),
("read_only_space", 0x0252d): (116, "FixedCOWArrayMap"),
("read_only_space", 0x02555): (117, "HashTableMap"),
("read_only_space", 0x0257d): (64, "SymbolMap"),
("read_only_space", 0x025a5): (40, "OneByteStringMap"),
("read_only_space", 0x025cd): (128, "ScopeInfoMap"),
("read_only_space", 0x025cd): (133, "ScopeInfoMap"),
("read_only_space", 0x025f5): (175, "SharedFunctionInfoMap"),
("read_only_space", 0x0261d): (160, "CodeMap"),
("read_only_space", 0x02645): (159, "CellMap"),
@ -264,16 +264,16 @@ KNOWN_MAPS = {
("read_only_space", 0x02805): (67, "TerminationExceptionMap"),
("read_only_space", 0x0286d): (67, "OptimizedOutMap"),
("read_only_space", 0x028cd): (67, "StaleRegisterMap"),
("read_only_space", 0x0292d): (129, "ScriptContextTableMap"),
("read_only_space", 0x0292d): (128, "ScriptContextTableMap"),
("read_only_space", 0x02955): (126, "ClosureFeedbackCellArrayMap"),
("read_only_space", 0x0297d): (164, "FeedbackMetadataArrayMap"),
("read_only_space", 0x029a5): (116, "ArrayListMap"),
("read_only_space", 0x029cd): (65, "BigIntMap"),
("read_only_space", 0x029f5): (127, "ObjectBoilerplateDescriptionMap"),
("read_only_space", 0x02a1d): (131, "BytecodeArrayMap"),
("read_only_space", 0x02a1d): (130, "BytecodeArrayMap"),
("read_only_space", 0x02a45): (161, "CodeDataContainerMap"),
("read_only_space", 0x02a6d): (162, "CoverageInfoMap"),
("read_only_space", 0x02a95): (132, "FixedDoubleArrayMap"),
("read_only_space", 0x02a95): (131, "FixedDoubleArrayMap"),
("read_only_space", 0x02abd): (119, "GlobalDictionaryMap"),
("read_only_space", 0x02ae5): (97, "ManyClosuresCellMap"),
("read_only_space", 0x02b0d): (116, "ModuleInfoMap"),
@ -368,7 +368,7 @@ KNOWN_MAPS = {
("read_only_space", 0x05afd): (146, "ExportedSubClassMap"),
("read_only_space", 0x05b25): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05b4d): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05b75): (133, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05b75): (132, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05b9d): (169, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05bc5): (147, "ExportedSubClass2Map"),
("read_only_space", 0x05bed): (178, "SortStateMap"),