Commit a177078a authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[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/1445882Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Commit-Queue: Daniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59321}
parent dc4c8bdb
......@@ -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");
}
}
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)");
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, ")");
}
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";
}
}
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";
CurrentSourcePosition::Scope scope(f.pos);
if (f.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
if (f.is_weak) {
ProcessFieldInSection(&section, &completed_sections,
FieldSectionType::kWeakSection,
&new_contents_stream);
} else {
ProcessFieldInSection(&section, &completed_sections,
FieldSectionType::kStrongSection,
&new_contents_stream);
}
} else {
ProcessFieldInSection(&section, &completed_sections,
FieldSectionType::kScalarSection,
&new_contents_stream);
}
}
new_contents_stream << "V(kEndOfWeakFieldsOffset, 0) \\\n";
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";
}
ProcessFieldInSection(&section, &completed_sections,
FieldSectionType::kNoSection, &new_contents_stream);
CompleteFieldSection(&section, &completed_sections,
FieldSectionType::kWeakSection, &new_contents_stream);
CompleteFieldSection(&section, &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;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment