[torque] Support non-tagged fields in classes
In the process add missing base Torque functionality for 8-bit and 16-bit integers and Cast<> operators to make them easy to use. As a poster child, port the field declarations of SharedFunctionInfo to the class definition in base.tq. As a drive by: Add the missing GN dependency on class-definitions-from-dsl.h Bug: v8:7793 Change-Id: I76a41c2e81ffd1cbb90ac7a4ef8d4003ac86e8dc Reviewed-on: https://chromium-review.googlesource.com/c/1445882 Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Commit-Queue: Daniel Clifford <danno@chromium.org> Cr-Commit-Position: refs/heads/master@{#59321}
This commit is contained in:
parent
dc4c8bdb05
commit
a177078acd
1
BUILD.gn
1
BUILD.gn
@ -930,6 +930,7 @@ action("run_torque") {
|
||||
|
||||
outputs = [
|
||||
"$target_gen_dir/torque-generated/builtin-definitions-from-dsl.h",
|
||||
"$target_gen_dir/torque-generated/class-definitions-from-dsl.h",
|
||||
]
|
||||
foreach(namespace, torque_namespaces) {
|
||||
outputs += [
|
||||
|
@ -28,7 +28,7 @@ namespace arguments {
|
||||
|
||||
const shared: SharedFunctionInfo = f.shared_function_info;
|
||||
const formalParameterCount: bint =
|
||||
Convert<bint>(shared.formal_parameter_count);
|
||||
Convert<bint>(Convert<int32>(shared.formal_parameter_count));
|
||||
let argumentCount: bint = formalParameterCount;
|
||||
|
||||
const adaptor: ArgumentsAdaptorFrame =
|
||||
|
@ -28,6 +28,17 @@ class HeapObject extends Tagged {
|
||||
type Object = Smi | HeapObject;
|
||||
type int32 generates 'TNode<Int32T>' constexpr 'int32_t';
|
||||
type uint32 generates 'TNode<Uint32T>' constexpr 'uint32_t';
|
||||
type int31 extends int32
|
||||
generates 'TNode<Int32T>' constexpr 'int31_t';
|
||||
type uint31 extends uint32
|
||||
generates 'TNode<Uint32T>' constexpr 'uint31_t';
|
||||
type int16 extends int31
|
||||
generates 'TNode<Int32T>' constexpr 'int16_t';
|
||||
type uint16 extends uint31
|
||||
generates 'TNode<Uint32T>' constexpr 'uint16_t';
|
||||
type int8 extends int16 generates 'TNode<Int32T>' constexpr 'int8_t';
|
||||
type uint8 extends uint16
|
||||
generates 'TNode<Uint32T>' constexpr 'uint8_t';
|
||||
type int64 generates 'TNode<Int64T>' constexpr 'int64_t';
|
||||
type intptr generates 'TNode<IntPtrT>' constexpr 'intptr_t';
|
||||
type uintptr generates 'TNode<UintPtrT>' constexpr 'uintptr_t';
|
||||
@ -37,8 +48,6 @@ type bool generates 'TNode<BoolT>' constexpr 'bool';
|
||||
type bint generates 'TNode<BInt>' constexpr 'BInt';
|
||||
type string constexpr 'const char*';
|
||||
|
||||
type int31 extends int32
|
||||
generates 'TNode<Int32T>' constexpr 'int31_t';
|
||||
type RawPtr generates 'TNode<RawPtrT>' constexpr 'void*';
|
||||
type AbstractCode extends HeapObject generates 'TNode<AbstractCode>';
|
||||
type Code extends AbstractCode generates 'TNode<Code>';
|
||||
@ -124,8 +133,28 @@ transient type FastJSArrayForCopy extends FastJSArray
|
||||
transient type FastJSArrayWithNoCustomIteration extends FastJSArray
|
||||
generates 'TNode<JSArray>';
|
||||
|
||||
type SharedFunctionInfo extends HeapObject
|
||||
generates 'TNode<SharedFunctionInfo>';
|
||||
type NoSharedNameSentinel extends Smi;
|
||||
type Script extends HeapObject;
|
||||
type DebugInfo extends HeapObject;
|
||||
|
||||
type ScopeInfo extends Object generates 'TNode<ScopeInfo>';
|
||||
|
||||
class SharedFunctionInfo extends HeapObject {
|
||||
weak function_data: Object;
|
||||
name_or_scope_info: String | NoSharedNameSentinel | ScopeInfo;
|
||||
outer_scope_info_or_feedback_metadata: HeapObject;
|
||||
script_or_debug_info: Script | DebugInfo;
|
||||
length: int16;
|
||||
formal_parameter_count: uint16;
|
||||
expected_nof_properties: int8;
|
||||
builtin_function_id: int8;
|
||||
function_token_offset: int16;
|
||||
flags: int32;
|
||||
}
|
||||
|
||||
class SharedFunctionInfoWithID extends SharedFunctionInfo {
|
||||
unique_id: int32;
|
||||
}
|
||||
|
||||
class JSFunction extends JSObject {
|
||||
shared_function_info: SharedFunctionInfo;
|
||||
@ -135,9 +164,6 @@ class JSFunction extends JSObject {
|
||||
weak prototype_or_initial_map: JSReceiver | Map;
|
||||
}
|
||||
|
||||
extern operator '.formal_parameter_count'
|
||||
macro LoadSharedFunctionInfoFormalParameterCount(SharedFunctionInfo): int32;
|
||||
|
||||
class JSBoundFunction extends JSObject {
|
||||
bound_target_function: JSReceiver;
|
||||
bound_this: Object;
|
||||
@ -870,9 +896,13 @@ extern macro ChangeUint32ToTagged(uint32): Number;
|
||||
extern macro ChangeUintPtrToFloat64(uintptr): float64;
|
||||
extern macro ChangeUintPtrToTagged(uintptr): Number;
|
||||
extern macro Unsigned(int32): uint32;
|
||||
extern macro Unsigned(int16): uint16;
|
||||
extern macro Unsigned(int8): uint8;
|
||||
extern macro Unsigned(intptr): uintptr;
|
||||
extern macro Unsigned(RawPtr): uintptr;
|
||||
extern macro Signed(uint32): int32;
|
||||
extern macro Signed(uint16): int16;
|
||||
extern macro Signed(uint8): int8;
|
||||
extern macro Signed(uintptr): intptr;
|
||||
extern macro Signed(RawPtr): intptr;
|
||||
extern macro TruncateIntPtrToInt32(intptr): int32;
|
||||
@ -1020,6 +1050,15 @@ Convert<Smi, uint32>(ui: uint32): Smi {
|
||||
Convert<uintptr, uint32>(ui: uint32): uintptr {
|
||||
return ChangeUint32ToWord(ui);
|
||||
}
|
||||
Convert<int32, uint8>(i: uint8): int32 {
|
||||
return Signed(Convert<uint32>(i));
|
||||
}
|
||||
Convert<int32, uint16>(i: uint16): int32 {
|
||||
return Signed(Convert<uint32>(i));
|
||||
}
|
||||
Convert<int32, uint31>(i: uint31): int32 {
|
||||
return Signed(Convert<uint32>(i));
|
||||
}
|
||||
Convert<int32, intptr>(i: intptr): int32 {
|
||||
return TruncateIntPtrToInt32(i);
|
||||
}
|
||||
|
@ -1180,13 +1180,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
TNode<BytecodeArray> LoadSharedFunctionInfoBytecodeArray(
|
||||
SloppyTNode<SharedFunctionInfo> shared);
|
||||
|
||||
TNode<Int32T> LoadSharedFunctionInfoFormalParameterCount(
|
||||
TNode<SharedFunctionInfo> function) {
|
||||
return TNode<Int32T>::UncheckedCast(LoadObjectField(
|
||||
function, SharedFunctionInfo::kFormalParameterCountOffset,
|
||||
MachineType::Uint16()));
|
||||
}
|
||||
|
||||
void StoreObjectByteNoWriteBarrier(TNode<HeapObject> object, int offset,
|
||||
TNode<Word32T> value);
|
||||
|
||||
|
@ -3675,7 +3675,8 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
|
||||
}
|
||||
share->set_script_or_debug_info(*undefined_value(), SKIP_WRITE_BARRIER);
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
|
||||
Handle<SharedFunctionInfoWithID>::cast(share)->set_unique_id(
|
||||
isolate()->GetNextUniqueSharedFunctionInfoId());
|
||||
#endif
|
||||
|
||||
// Set integer fields (smi or int, depending on the architecture).
|
||||
|
@ -496,8 +496,13 @@ bool Heap::CreateInitialMaps() {
|
||||
ALLOCATE_MAP(UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE,
|
||||
UncompiledDataWithPreparseData::kSize,
|
||||
uncompiled_data_with_preparse_data)
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE,
|
||||
SharedFunctionInfoWithID::kAlignedSize, shared_function_info)
|
||||
#else
|
||||
ALLOCATE_MAP(SHARED_FUNCTION_INFO_TYPE, SharedFunctionInfo::kAlignedSize,
|
||||
shared_function_info)
|
||||
#endif
|
||||
|
||||
ALLOCATE_MAP(CODE_DATA_CONTAINER_TYPE, CodeDataContainer::kSize,
|
||||
code_data_container)
|
||||
|
@ -1664,7 +1664,7 @@ void Logger::MapEvent(const char* type, Map from, Map to, const char* reason,
|
||||
SharedFunctionInfo sfi = SharedFunctionInfo::cast(name_or_sfi);
|
||||
msg << sfi->DebugName();
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
msg << " " << sfi->unique_id();
|
||||
msg << " " << SharedFunctionInfoWithID::cast(sfi)->unique_id();
|
||||
#endif // V8_SFI_HAS_UNIQUE_ID
|
||||
}
|
||||
}
|
||||
|
@ -247,8 +247,7 @@ class SharedFunctionInfo::BodyDescriptor final : public BodyDescriptorBase {
|
||||
static inline void IterateBody(Map map, HeapObject obj, int object_size,
|
||||
ObjectVisitor* v) {
|
||||
IterateCustomWeakPointer(obj, kFunctionDataOffset, v);
|
||||
IteratePointers(obj,
|
||||
SharedFunctionInfo::kStartOfAlwaysStrongPointerFieldsOffset,
|
||||
IteratePointers(obj, SharedFunctionInfo::kStartOfStrongFieldsOffset,
|
||||
SharedFunctionInfo::kEndOfTaggedFieldsOffset, v);
|
||||
}
|
||||
|
||||
|
@ -124,15 +124,13 @@ ACCESSORS(SharedFunctionInfo, name_or_scope_info, Object,
|
||||
ACCESSORS(SharedFunctionInfo, script_or_debug_info, Object,
|
||||
kScriptOrDebugInfoOffset)
|
||||
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
INT_ACCESSORS(SharedFunctionInfo, unique_id, kUniqueIdOffset)
|
||||
#endif
|
||||
UINT16_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
|
||||
UINT16_ACCESSORS(SharedFunctionInfo, internal_formal_parameter_count,
|
||||
kFormalParameterCountOffset)
|
||||
UINT8_ACCESSORS(SharedFunctionInfo, expected_nof_properties,
|
||||
kExpectedNofPropertiesOffset)
|
||||
UINT8_ACCESSORS(SharedFunctionInfo, raw_builtin_function_id, kBuiltinFunctionId)
|
||||
UINT8_ACCESSORS(SharedFunctionInfo, raw_builtin_function_id,
|
||||
kBuiltinFunctionIdOffset)
|
||||
UINT16_ACCESSORS(SharedFunctionInfo, raw_function_token_offset,
|
||||
kFunctionTokenOffsetOffset)
|
||||
RELAXED_INT32_ACCESSORS(SharedFunctionInfo, flags, kFlagsOffset)
|
||||
@ -633,6 +631,10 @@ void SharedFunctionInfo::ClearPreparseData() {
|
||||
DCHECK(HasUncompiledDataWithoutPreparseData());
|
||||
}
|
||||
|
||||
OBJECT_CONSTRUCTORS_IMPL(SharedFunctionInfoWithID, SharedFunctionInfo)
|
||||
CAST_ACCESSOR(SharedFunctionInfoWithID)
|
||||
INT_ACCESSORS(SharedFunctionInfoWithID, unique_id, kUniqueIdOffset)
|
||||
|
||||
// static
|
||||
void UncompiledData::Initialize(
|
||||
UncompiledData data, String inferred_name, int start_position,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "src/objects/script.h"
|
||||
#include "src/objects/smi.h"
|
||||
#include "src/objects/struct.h"
|
||||
#include "torque-generated/class-definitions-from-dsl.h"
|
||||
|
||||
// Has to be the last include (doesn't have include guards):
|
||||
#include "src/objects/object-macros.h"
|
||||
@ -322,12 +323,6 @@ class SharedFunctionInfo : public HeapObject {
|
||||
// function. The value is only reliable when the function has been compiled.
|
||||
DECL_UINT8_ACCESSORS(expected_nof_properties)
|
||||
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
// [unique_id] - For --trace-maps purposes, an identifier that's persistent
|
||||
// even if the GC moves this SharedFunctionInfo.
|
||||
DECL_INT_ACCESSORS(unique_id)
|
||||
#endif
|
||||
|
||||
// [function data]: This field holds some additional data for function.
|
||||
// Currently it has one of:
|
||||
// - a FunctionTemplateInfo to make benefit the API [IsApiFunction()].
|
||||
@ -647,37 +642,8 @@ class SharedFunctionInfo : public HeapObject {
|
||||
static const uint16_t kFunctionTokenOutOfRange = static_cast<uint16_t>(-1);
|
||||
STATIC_ASSERT(kMaximumFunctionTokenOffset + 1 == kFunctionTokenOutOfRange);
|
||||
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
static const int kUniqueIdFieldSize = kInt32Size;
|
||||
#else
|
||||
// Just to not break the postmortrem support with conditional offsets
|
||||
static const int kUniqueIdFieldSize = 0;
|
||||
#endif
|
||||
|
||||
// Layout description.
|
||||
#define SHARED_FUNCTION_INFO_FIELDS(V) \
|
||||
/* Pointer fields. */ \
|
||||
V(kStartOfPointerFieldsOffset, 0) \
|
||||
V(kFunctionDataOffset, kTaggedSize) \
|
||||
V(kStartOfAlwaysStrongPointerFieldsOffset, 0) \
|
||||
V(kNameOrScopeInfoOffset, kTaggedSize) \
|
||||
V(kOuterScopeInfoOrFeedbackMetadataOffset, kTaggedSize) \
|
||||
V(kScriptOrDebugInfoOffset, kTaggedSize) \
|
||||
V(kEndOfTaggedFieldsOffset, 0) \
|
||||
/* Raw data fields. */ \
|
||||
V(kUniqueIdOffset, kUniqueIdFieldSize) \
|
||||
V(kLengthOffset, kUInt16Size) \
|
||||
V(kFormalParameterCountOffset, kUInt16Size) \
|
||||
V(kExpectedNofPropertiesOffset, kUInt8Size) \
|
||||
V(kBuiltinFunctionId, kUInt8Size) \
|
||||
V(kFunctionTokenOffsetOffset, kUInt16Size) \
|
||||
V(kFlagsOffset, kInt32Size) \
|
||||
/* Total size. */ \
|
||||
V(kSize, 0)
|
||||
|
||||
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
|
||||
SHARED_FUNCTION_INFO_FIELDS)
|
||||
#undef SHARED_FUNCTION_INFO_FIELDS
|
||||
|
||||
static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
|
||||
|
||||
@ -720,6 +686,14 @@ class SharedFunctionInfo : public HeapObject {
|
||||
// This is needed to set up the [[HomeObject]] on the function instance.
|
||||
inline bool needs_home_object() const;
|
||||
|
||||
V8_INLINE bool IsSharedFunctionInfoWithID() const {
|
||||
#if V8_SFI_HAS_UNIQUE_ID
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
// [name_or_scope_info]: Function name string, kNoSharedNameSentinel or
|
||||
// ScopeInfo.
|
||||
@ -746,6 +720,22 @@ class SharedFunctionInfo : public HeapObject {
|
||||
OBJECT_CONSTRUCTORS(SharedFunctionInfo, HeapObject);
|
||||
};
|
||||
|
||||
class SharedFunctionInfoWithID : public SharedFunctionInfo {
|
||||
public:
|
||||
// [unique_id] - For --trace-maps purposes, an identifier that's persistent
|
||||
// even if the GC moves this SharedFunctionInfo.
|
||||
DECL_INT_ACCESSORS(unique_id)
|
||||
|
||||
DECL_CAST(SharedFunctionInfoWithID)
|
||||
|
||||
DEFINE_FIELD_OFFSET_CONSTANTS(SharedFunctionInfo::kSize,
|
||||
SHARED_FUNCTION_INFO_WITH_ID_FIELDS)
|
||||
|
||||
static const int kAlignedSize = POINTER_SIZE_ALIGN(kSize);
|
||||
|
||||
OBJECT_CONSTRUCTORS(SharedFunctionInfoWithID, SharedFunctionInfo)
|
||||
};
|
||||
|
||||
// Printing support.
|
||||
struct SourceCodeOf {
|
||||
explicit SourceCodeOf(SharedFunctionInfo v, int max = -1)
|
||||
|
@ -683,17 +683,21 @@ void CSAGenerator::EmitInstruction(
|
||||
const Field& field =
|
||||
instruction.class_type->LookupField(instruction.field_name);
|
||||
std::string result_name = FreshNodeName();
|
||||
std::string type_string =
|
||||
field.name_and_type.type->IsSubtypeOf(TypeOracle::GetSmiType())
|
||||
? "MachineType::TaggedSigned()"
|
||||
: "MachineType::AnyTagged()";
|
||||
|
||||
size_t field_size;
|
||||
std::string size_string;
|
||||
std::string machine_type;
|
||||
std::tie(field_size, size_string, machine_type) =
|
||||
field.GetFieldSizeInformation();
|
||||
|
||||
out_ << field.name_and_type.type->GetGeneratedTypeName() << " " << result_name
|
||||
<< " = "
|
||||
<< "ca_.UncheckedCast<"
|
||||
<< field.name_and_type.type->GetGeneratedTNodeTypeName()
|
||||
<< ">(CodeStubAssembler(state_).LoadObjectField("
|
||||
<< stack->Top() + ", " + std::to_string(field.offset) + ", "
|
||||
<< type_string + "));\n";
|
||||
<< stack->Top() + ", " + field.aggregate->GetGeneratedTNodeTypeName() +
|
||||
"::k" + CamelifyString(field.name_and_type.name) + "Offset, "
|
||||
<< machine_type + "));\n";
|
||||
stack->Poke(stack->AboveTop() - 1, result_name);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "src/torque/declarable.h"
|
||||
#include "src/torque/global-context.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -95,6 +96,12 @@ base::Optional<TypeVector> Generic::InferSpecializationTypes(
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Namespace::IsDefaultNamespace() const {
|
||||
return this == GlobalContext::GetDefaultNamespace();
|
||||
}
|
||||
|
||||
bool Namespace::IsTestNamespace() const { return name() == kTestNamespaceName; }
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -158,6 +158,8 @@ class Namespace : public Scope {
|
||||
std::string ExternalName() const {
|
||||
return CamelifyString(name()) + "BuiltinsFromDSLAssembler";
|
||||
}
|
||||
bool IsDefaultNamespace() const;
|
||||
bool IsTestNamespace() const;
|
||||
std::ostream& source_stream() { return source_stream_; }
|
||||
std::ostream& header_stream() { return header_stream_; }
|
||||
std::string source() { return source_stream_.str(); }
|
||||
|
@ -515,6 +515,7 @@ void DeclarationVisitor::FinalizeStructFieldsAndMethods(
|
||||
for (auto& field : struct_declaration->fields) {
|
||||
const Type* field_type = Declarations::GetType(field.name_and_type.type);
|
||||
struct_type->RegisterField({field.name_and_type.type->pos,
|
||||
struct_type,
|
||||
{field.name_and_type.name, field_type},
|
||||
offset,
|
||||
false});
|
||||
@ -528,40 +529,29 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
|
||||
ClassType* class_type, ClassDeclaration* class_declaration) {
|
||||
const ClassType* super_class = class_type->GetSuperClass();
|
||||
size_t class_offset = super_class ? super_class->size() : 0;
|
||||
bool seen_strong = false;
|
||||
bool seen_weak = false;
|
||||
for (ClassFieldExpression& field : class_declaration->fields) {
|
||||
for (ClassFieldExpression& field_expression : class_declaration->fields) {
|
||||
CurrentSourcePosition::Scope position_activator(
|
||||
field.name_and_type.type->pos);
|
||||
const Type* field_type = Declarations::GetType(field.name_and_type.type);
|
||||
if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
|
||||
if (field.weak) {
|
||||
seen_weak = true;
|
||||
} else {
|
||||
if (seen_weak) {
|
||||
ReportError("cannot declare strong field \"",
|
||||
field.name_and_type.name,
|
||||
"\" after weak Tagged references");
|
||||
}
|
||||
seen_strong = true;
|
||||
}
|
||||
} else {
|
||||
if (seen_strong || seen_weak) {
|
||||
ReportError("cannot declare scalar field \"", field.name_and_type.name,
|
||||
"\" after strong or weak Tagged references");
|
||||
}
|
||||
field_expression.name_and_type.type->pos);
|
||||
const Type* field_type =
|
||||
Declarations::GetType(field_expression.name_and_type.type);
|
||||
const Field& field = class_type->RegisterField(
|
||||
{field_expression.name_and_type.type->pos,
|
||||
class_type,
|
||||
{field_expression.name_and_type.name, field_type},
|
||||
class_offset,
|
||||
field_expression.weak});
|
||||
size_t field_size;
|
||||
std::string size_string;
|
||||
std::string machine_type;
|
||||
std::tie(field_size, size_string, machine_type) =
|
||||
field.GetFieldSizeInformation();
|
||||
size_t aligned_offset = class_offset & ~(field_size - 1);
|
||||
if (class_offset != aligned_offset) {
|
||||
ReportError("field ", field_expression.name_and_type.name,
|
||||
" is not aligned to its size (", aligned_offset, " vs ",
|
||||
class_offset, " for field size ", field_size, ")");
|
||||
}
|
||||
if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
|
||||
ReportError(
|
||||
"field \"", field.name_and_type.name, "\" of class \"",
|
||||
class_declaration->name,
|
||||
"\" must be a subtype of Tagged (other types not yet supported)");
|
||||
}
|
||||
class_type->RegisterField({field.name_and_type.type->pos,
|
||||
{field.name_and_type.name, field_type},
|
||||
class_offset,
|
||||
field.weak});
|
||||
class_offset += kTaggedSize;
|
||||
class_offset += field_size;
|
||||
}
|
||||
class_type->SetSize(class_offset);
|
||||
|
||||
@ -579,6 +569,7 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
|
||||
super_struct_type = super_class->struct_type();
|
||||
this_struct_type->RegisterField(
|
||||
{CurrentSourcePosition::Get(),
|
||||
super_struct_type,
|
||||
{kConstructorStructSuperFieldName, super_struct_type},
|
||||
struct_offset,
|
||||
false});
|
||||
@ -587,6 +578,7 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
|
||||
for (auto& field : class_type->fields()) {
|
||||
const Type* field_type = field.name_and_type.type;
|
||||
this_struct_type->RegisterField({field.pos,
|
||||
class_type,
|
||||
{field.name_and_type.name, field_type},
|
||||
struct_offset,
|
||||
false});
|
||||
|
@ -22,7 +22,7 @@ class GlobalContext : public ContextualClass<GlobalContext> {
|
||||
CurrentSourcePosition::Scope current_source_position(
|
||||
SourcePosition{CurrentSourceFile::Get(), -1, -1});
|
||||
default_namespace_ =
|
||||
RegisterDeclarable(base::make_unique<Namespace>("base"));
|
||||
RegisterDeclarable(base::make_unique<Namespace>(kBaseNamespaceName));
|
||||
}
|
||||
static Namespace* GetDefaultNamespace() { return Get().default_namespace_; }
|
||||
template <class T>
|
||||
@ -46,12 +46,11 @@ class GlobalContext : public ContextualClass<GlobalContext> {
|
||||
return result;
|
||||
}
|
||||
|
||||
static void RegisterClass(const std::string& name,
|
||||
const ClassType* new_class) {
|
||||
static void RegisterClass(const std::string& name, ClassType* new_class) {
|
||||
Get().classes_[name] = new_class;
|
||||
}
|
||||
|
||||
static const std::map<std::string, const ClassType*>& GetClasses() {
|
||||
static const std::map<std::string, ClassType*>& GetClasses() {
|
||||
return Get().classes_;
|
||||
}
|
||||
|
||||
@ -72,7 +71,7 @@ class GlobalContext : public ContextualClass<GlobalContext> {
|
||||
Ast ast_;
|
||||
std::vector<std::unique_ptr<Declarable>> declarables_;
|
||||
std::vector<std::string> cpp_includes_;
|
||||
std::map<std::string, const ClassType*> classes_;
|
||||
std::map<std::string, ClassType*> classes_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@ -74,6 +74,8 @@ void ImplementationVisitor::BeginNamespaceFile(Namespace* nspace) {
|
||||
if (nspace != GlobalContext::GetDefaultNamespace()) {
|
||||
header << "#include \"src/code-stub-assembler.h\"\n";
|
||||
}
|
||||
header << "#include \"src/utils.h\"\n";
|
||||
header << "#include \"torque-generated/class-definitions-from-dsl.h\"\n";
|
||||
header << "\n";
|
||||
|
||||
header << "namespace v8 {\n"
|
||||
@ -147,6 +149,32 @@ void ImplementationVisitor::Visit(NamespaceConstant* decl) {
|
||||
|
||||
void ImplementationVisitor::Visit(TypeAlias* alias) {
|
||||
if (alias->IsRedeclaration()) return;
|
||||
const ClassType* class_type = ClassType::DynamicCast(alias->type());
|
||||
if (class_type) {
|
||||
// Classes that are in the default namespace are defined in the C++
|
||||
// world and all of their fields and methods are declared explicitly.
|
||||
// Internal classes (e.g. ones used for testing that are not in the default
|
||||
// name space) need to be defined by Torque.
|
||||
// TODO(danno): This is a pretty cheesy hack for now. There should be a more
|
||||
// robust mechanism for this, e.g. declaring classes 'extern' or something.
|
||||
if (class_type->nspace()->IsTestNamespace()) {
|
||||
std::string class_name{
|
||||
class_type->GetSuperClass()->GetGeneratedTNodeTypeName()};
|
||||
header_out() << " class " << class_type->name() << " : public "
|
||||
<< class_name << " {\n";
|
||||
header_out() << " public:\n";
|
||||
header_out() << " DEFINE_FIELD_OFFSET_CONSTANTS(" << class_name
|
||||
<< "::kSize, "
|
||||
<< CapifyStringWithUnderscores(class_type->name())
|
||||
<< "_FIELDS)\n";
|
||||
header_out() << " };\n";
|
||||
} else if (!class_type->nspace()->IsDefaultNamespace()) {
|
||||
ReportError(
|
||||
"classes are currently only supported in the default and test "
|
||||
"namespaces");
|
||||
}
|
||||
return;
|
||||
}
|
||||
const StructType* struct_type = StructType::DynamicCast(alias->type());
|
||||
if (!struct_type) return;
|
||||
const std::string& name = struct_type->name();
|
||||
@ -1224,6 +1252,12 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) {
|
||||
"\" is not");
|
||||
}
|
||||
|
||||
if (!class_type->AllowInstantiation()) {
|
||||
// Classes that are only used for testing should never be instantiated.
|
||||
ReportError(*class_type,
|
||||
" cannot be allocated with new (it's used for testing)");
|
||||
}
|
||||
|
||||
// In order to ensure "atomicity" of object allocation, a class' constructors
|
||||
// operate on a per-class internal struct rather than the class directly until
|
||||
// the constructor has successfully completed and all class members are
|
||||
@ -2510,6 +2544,79 @@ void ImplementationVisitor::GenerateBuiltinDefinitions(std::string& file_name) {
|
||||
ReplaceFileContentsIfDifferent(file_name, new_contents);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
enum class FieldSectionType {
|
||||
kNoSection = 0,
|
||||
kWeakSection,
|
||||
kStrongSection,
|
||||
kScalarSection
|
||||
};
|
||||
|
||||
void PossiblyStartTagged(FieldSectionType* section,
|
||||
std::set<FieldSectionType>* completed_sections,
|
||||
std::stringstream* o) {
|
||||
if (completed_sections->count(FieldSectionType::kWeakSection) == 0 &&
|
||||
completed_sections->count(FieldSectionType::kStrongSection) == 0 &&
|
||||
*section != FieldSectionType::kWeakSection &&
|
||||
*section != FieldSectionType::kStrongSection) {
|
||||
*o << "V(kStartOfPointerFieldsOffset, 0) \\\n";
|
||||
}
|
||||
}
|
||||
|
||||
void PossiblyEndTagged(FieldSectionType* section,
|
||||
std::set<FieldSectionType>* completed_sections,
|
||||
std::stringstream* o) {
|
||||
if (completed_sections->count(FieldSectionType::kWeakSection) != 0 &&
|
||||
completed_sections->count(FieldSectionType::kStrongSection) != 0) {
|
||||
*o << "V(kEndOfTaggedFieldsOffset, 0) \\\n";
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessFieldInSection(FieldSectionType* section,
|
||||
std::set<FieldSectionType>* completed_sections,
|
||||
FieldSectionType field_section,
|
||||
std::stringstream* o) {
|
||||
if (*section != FieldSectionType::kNoSection) {
|
||||
if (*section != field_section) {
|
||||
if (completed_sections->count(field_section) != 0) {
|
||||
ReportError("reopening of weak, strong or scalar field section");
|
||||
}
|
||||
completed_sections->insert(*section);
|
||||
if (*section == FieldSectionType::kWeakSection) {
|
||||
*o << "V(kEndOfWeakFieldsOffset, 0) \\\n";
|
||||
PossiblyEndTagged(section, completed_sections, o);
|
||||
} else if (*section == FieldSectionType::kStrongSection) {
|
||||
*o << "V(kEndOfStrongFieldsOffset, 0) \\\n";
|
||||
PossiblyEndTagged(section, completed_sections, o);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*section != field_section) {
|
||||
if (field_section == FieldSectionType::kWeakSection) {
|
||||
PossiblyStartTagged(section, completed_sections, o);
|
||||
*o << "V(kStartOfWeakFieldsOffset, 0) \\\n";
|
||||
} else if (field_section == FieldSectionType::kStrongSection) {
|
||||
PossiblyStartTagged(section, completed_sections, o);
|
||||
*o << "V(kStartOfStrongFieldsOffset, 0) \\\n";
|
||||
}
|
||||
}
|
||||
*section = field_section;
|
||||
}
|
||||
|
||||
void CompleteFieldSection(FieldSectionType* section,
|
||||
std::set<FieldSectionType>* completed_sections,
|
||||
FieldSectionType field_section,
|
||||
std::stringstream* o) {
|
||||
if (completed_sections->count(field_section) == 0) {
|
||||
ProcessFieldInSection(section, completed_sections, field_section, o);
|
||||
ProcessFieldInSection(section, completed_sections,
|
||||
FieldSectionType::kNoSection, o);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ImplementationVisitor::GenerateClassDefinitions(std::string& file_name) {
|
||||
std::stringstream new_contents_stream;
|
||||
new_contents_stream << "#ifndef V8_CLASS_BUILTIN_DEFINITIONS_FROM_DSL_H_\n"
|
||||
@ -2525,24 +2632,44 @@ void ImplementationVisitor::GenerateClassDefinitions(std::string& file_name) {
|
||||
new_contents_stream << "#define ";
|
||||
new_contents_stream << CapifyStringWithUnderscores(i.first)
|
||||
<< "_FIELDS(V) \\\n";
|
||||
const ClassType* type = i.second;
|
||||
ClassType* type = i.second;
|
||||
std::vector<Field> fields = type->fields();
|
||||
new_contents_stream << "V(kStartOfStrongFieldsOffset, 0) \\\n";
|
||||
FieldSectionType section = FieldSectionType::kNoSection;
|
||||
std::set<FieldSectionType> completed_sections;
|
||||
for (auto f : fields) {
|
||||
if (!f.is_weak) {
|
||||
new_contents_stream << "V(k" << CamelifyString(f.name_and_type.name)
|
||||
<< "Offset, kTaggedSize) \\\n";
|
||||
CurrentSourcePosition::Scope scope(f.pos);
|
||||
if (f.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
|
||||
if (f.is_weak) {
|
||||
ProcessFieldInSection(§ion, &completed_sections,
|
||||
FieldSectionType::kWeakSection,
|
||||
&new_contents_stream);
|
||||
} else {
|
||||
ProcessFieldInSection(§ion, &completed_sections,
|
||||
FieldSectionType::kStrongSection,
|
||||
&new_contents_stream);
|
||||
}
|
||||
} else {
|
||||
ProcessFieldInSection(§ion, &completed_sections,
|
||||
FieldSectionType::kScalarSection,
|
||||
&new_contents_stream);
|
||||
}
|
||||
size_t field_size;
|
||||
std::string size_string;
|
||||
std::string machine_type;
|
||||
std::tie(field_size, size_string, machine_type) =
|
||||
f.GetFieldSizeInformation();
|
||||
new_contents_stream << "V(k" << CamelifyString(f.name_and_type.name)
|
||||
<< "Offset, " << size_string << ") \\\n";
|
||||
}
|
||||
new_contents_stream << "V(kEndOfStrongFieldsOffset, 0) \\\n";
|
||||
new_contents_stream << "V(kStartOfWeakFieldsOffset, 0) \\\n";
|
||||
for (auto f : fields) {
|
||||
if (f.is_weak) {
|
||||
new_contents_stream << "V(k" << CamelifyString(f.name_and_type.name)
|
||||
<< "Offset, kTaggedSize) \\\n";
|
||||
}
|
||||
}
|
||||
new_contents_stream << "V(kEndOfWeakFieldsOffset, 0) \\\n";
|
||||
|
||||
ProcessFieldInSection(§ion, &completed_sections,
|
||||
FieldSectionType::kNoSection, &new_contents_stream);
|
||||
CompleteFieldSection(§ion, &completed_sections,
|
||||
FieldSectionType::kWeakSection, &new_contents_stream);
|
||||
CompleteFieldSection(§ion, &completed_sections,
|
||||
FieldSectionType::kStrongSection,
|
||||
&new_contents_stream);
|
||||
|
||||
new_contents_stream << "V(kSize, 0) \\\n";
|
||||
new_contents_stream << "\n";
|
||||
}
|
||||
|
@ -147,6 +147,26 @@ class TypeOracle : public ContextualClass<TypeOracle> {
|
||||
return Get().GetBuiltinType(INT32_TYPE_STRING);
|
||||
}
|
||||
|
||||
static const Type* GetUint32Type() {
|
||||
return Get().GetBuiltinType(UINT32_TYPE_STRING);
|
||||
}
|
||||
|
||||
static const Type* GetInt16Type() {
|
||||
return Get().GetBuiltinType(INT16_TYPE_STRING);
|
||||
}
|
||||
|
||||
static const Type* GetUint16Type() {
|
||||
return Get().GetBuiltinType(UINT16_TYPE_STRING);
|
||||
}
|
||||
|
||||
static const Type* GetInt8Type() {
|
||||
return Get().GetBuiltinType(INT8_TYPE_STRING);
|
||||
}
|
||||
|
||||
static const Type* GetUint8Type() {
|
||||
return Get().GetBuiltinType(UINT8_TYPE_STRING);
|
||||
}
|
||||
|
||||
static const Type* GetNeverType() {
|
||||
return Get().GetBuiltinType(NEVER_TYPE_STRING);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "src/globals.h"
|
||||
#include "src/torque/declarable.h"
|
||||
#include "src/torque/type-oracle.h"
|
||||
#include "src/torque/types.h"
|
||||
@ -78,8 +79,6 @@ std::string AbstractType::GetGeneratedTNodeTypeName() const {
|
||||
return generated_type_;
|
||||
}
|
||||
|
||||
std::string ClassType::GetGeneratedTNodeTypeName() const { return generates_; }
|
||||
|
||||
std::string BuiltinPointerType::ToExplicitString() const {
|
||||
std::stringstream result;
|
||||
result << "builtin (";
|
||||
@ -262,6 +261,18 @@ std::string StructType::ToExplicitString() const {
|
||||
return result.str();
|
||||
}
|
||||
|
||||
std::string ClassType::GetGeneratedTNodeTypeName() const {
|
||||
std::string prefix = nspace()->IsDefaultNamespace()
|
||||
? std::string{}
|
||||
: (nspace()->ExternalName() + "::");
|
||||
return prefix + generates_;
|
||||
}
|
||||
|
||||
std::string ClassType::GetGeneratedTypeName() const {
|
||||
return IsConstexpr() ? GetGeneratedTNodeTypeName()
|
||||
: "compiler::TNode<" + GetGeneratedTNodeTypeName() + ">";
|
||||
}
|
||||
|
||||
std::string ClassType::ToExplicitString() const {
|
||||
std::stringstream result;
|
||||
result << "class " << name() << "{";
|
||||
@ -270,6 +281,10 @@ std::string ClassType::ToExplicitString() const {
|
||||
return result.str();
|
||||
}
|
||||
|
||||
bool ClassType::AllowInstantiation() const {
|
||||
return nspace()->IsDefaultNamespace();
|
||||
}
|
||||
|
||||
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
|
||||
os << "(";
|
||||
for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) {
|
||||
@ -469,6 +484,60 @@ VisitResult VisitResult::NeverResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::tuple<size_t, std::string, std::string> Field::GetFieldSizeInformation()
|
||||
const {
|
||||
std::string size_string = "#no size";
|
||||
std::string machine_type = "#no machine type";
|
||||
const Type* field_type = this->name_and_type.type;
|
||||
size_t field_size = 0;
|
||||
if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
|
||||
field_size = kTaggedSize;
|
||||
size_string = "kTaggedSize";
|
||||
machine_type = field_type->IsSubtypeOf(TypeOracle::GetSmiType())
|
||||
? "MachineType::TaggedSigned()"
|
||||
: "MachineType::AnyTagged()";
|
||||
} else if (field_type->IsSubtypeOf(TypeOracle::GetRawPtrType())) {
|
||||
field_size = kSystemPointerSize;
|
||||
size_string = "kSystemPointerSize";
|
||||
machine_type = "MachineType::Pointer()";
|
||||
} else if (field_type == TypeOracle::GetInt32Type()) {
|
||||
field_size = kInt32Size;
|
||||
size_string = "kInt32Size";
|
||||
machine_type = "MachineType::Int32()";
|
||||
} else if (field_type == TypeOracle::GetUint32Type()) {
|
||||
field_size = kInt32Size;
|
||||
size_string = "kInt32Size";
|
||||
machine_type = "MachineType::Uint32()";
|
||||
} else if (field_type == TypeOracle::GetInt16Type()) {
|
||||
field_size = kUInt16Size;
|
||||
size_string = "kUInt16Size";
|
||||
machine_type = "MachineType::Int16()";
|
||||
} else if (field_type == TypeOracle::GetUint16Type()) {
|
||||
field_size = kUInt16Size;
|
||||
size_string = "kUInt16Size";
|
||||
machine_type = "MachineType::Uint16()";
|
||||
} else if (field_type == TypeOracle::GetInt8Type()) {
|
||||
field_size = kUInt8Size;
|
||||
size_string = "kUInt8Size";
|
||||
machine_type = "MachineType::Int8()";
|
||||
} else if (field_type == TypeOracle::GetUint8Type()) {
|
||||
field_size = kUInt8Size;
|
||||
size_string = "kUInt8Size";
|
||||
machine_type = "MachineType::Uint8()";
|
||||
} else if (field_type == TypeOracle::GetIntPtrType()) {
|
||||
field_size = kIntptrSize;
|
||||
size_string = "kIntptrSize";
|
||||
machine_type = "MachineType::IntPtr()";
|
||||
} else if (field_type == TypeOracle::GetUIntPtrType()) {
|
||||
field_size = kIntptrSize;
|
||||
size_string = "kIntptrSize";
|
||||
machine_type = "MachineType::IntPtr()";
|
||||
} else {
|
||||
ReportError("fields of type ", *field_type, " are not (yet) supported");
|
||||
}
|
||||
return std::make_tuple(field_size, size_string, machine_type);
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -39,10 +39,16 @@ static const char* const BUILTIN_POINTER_TYPE_STRING = "BuiltinPtr";
|
||||
static const char* const INTPTR_TYPE_STRING = "intptr";
|
||||
static const char* const UINTPTR_TYPE_STRING = "uintptr";
|
||||
static const char* const INT32_TYPE_STRING = "int32";
|
||||
static const char* const UINT32_TYPE_STRING = "uint32";
|
||||
static const char* const INT16_TYPE_STRING = "int16";
|
||||
static const char* const UINT16_TYPE_STRING = "uint16";
|
||||
static const char* const INT8_TYPE_STRING = "int8";
|
||||
static const char* const UINT8_TYPE_STRING = "uint8";
|
||||
static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
|
||||
static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
|
||||
static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
|
||||
|
||||
class AggregateType;
|
||||
class Macro;
|
||||
class Method;
|
||||
class StructType;
|
||||
@ -154,7 +160,10 @@ struct NameAndType {
|
||||
std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);
|
||||
|
||||
struct Field {
|
||||
std::tuple<size_t, std::string, std::string> GetFieldSizeInformation() const;
|
||||
|
||||
SourcePosition pos;
|
||||
const AggregateType* aggregate;
|
||||
NameAndType name_and_type;
|
||||
size_t offset;
|
||||
bool is_weak;
|
||||
@ -402,7 +411,10 @@ class AggregateType : public Type {
|
||||
return "_method_" + name_ + "_" + name;
|
||||
}
|
||||
|
||||
void RegisterField(Field field) { fields_.push_back(field); }
|
||||
const Field& RegisterField(Field field) {
|
||||
fields_.push_back(field);
|
||||
return fields_.back();
|
||||
}
|
||||
|
||||
void RegisterMethod(Method* method) { methods_.push_back(method); }
|
||||
std::vector<Method*> Constructors() const;
|
||||
@ -454,9 +466,7 @@ class ClassType final : public AggregateType {
|
||||
public:
|
||||
DECLARE_TYPE_BOILERPLATE(ClassType);
|
||||
std::string ToExplicitString() const override;
|
||||
std::string GetGeneratedTypeName() const override {
|
||||
return IsConstexpr() ? generates_ : "compiler::TNode<" + generates_ + ">";
|
||||
}
|
||||
std::string GetGeneratedTypeName() const override;
|
||||
std::string GetGeneratedTNodeTypeName() const override;
|
||||
bool IsTransient() const override { return transient_; }
|
||||
size_t size() const { return size_; }
|
||||
@ -467,6 +477,7 @@ class ClassType final : public AggregateType {
|
||||
}
|
||||
void SetSize(size_t size) { size_ = size; }
|
||||
void SetThisStruct(StructType* this_struct) { this_struct_ = this_struct; }
|
||||
bool AllowInstantiation() const;
|
||||
|
||||
private:
|
||||
friend class TypeOracle;
|
||||
|
@ -125,8 +125,9 @@ bool IsKeywordLikeName(const std::string& s) {
|
||||
// naming convention and are those exempt from the normal type convention.
|
||||
bool IsMachineType(const std::string& s) {
|
||||
static const char* const machine_types[]{
|
||||
"void", "never", "int32", "uint32", "int64", "intptr", "uintptr",
|
||||
"float32", "float64", "bool", "string", "bint", "int31"};
|
||||
"void", "never", "int8", "uint8", "int16", "uint16",
|
||||
"int31", "uint31", "int32", "uint32", "int64", "intptr",
|
||||
"uintptr", "float32", "float64", "bool", "string", "bint"};
|
||||
|
||||
return std::find(std::begin(machine_types), std::end(machine_types), s) !=
|
||||
std::end(machine_types);
|
||||
|
@ -272,6 +272,8 @@ class ToString {
|
||||
|
||||
constexpr int kTaggedSize = sizeof(void*);
|
||||
|
||||
static const char* const kBaseNamespaceName = "base";
|
||||
static const char* const kTestNamespaceName = "test";
|
||||
static const char* const kConstructMethodName = "constructor";
|
||||
static const char* const kSuperMethodName = "super";
|
||||
static const char* const kConstructorStructSuperFieldName = "_super";
|
||||
|
@ -768,4 +768,18 @@ namespace test {
|
||||
assert(w.c == 1);
|
||||
assert(w.d == 2);
|
||||
}
|
||||
|
||||
class TestClassWithAllTypes extends JSObject {
|
||||
a: int8;
|
||||
b: uint8;
|
||||
b2: uint8;
|
||||
b3: uint8;
|
||||
c: int16;
|
||||
d: uint16;
|
||||
e: int32;
|
||||
f: uint32;
|
||||
g: RawPtr;
|
||||
h: intptr;
|
||||
i: uintptr;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user