diff options
Diffstat (limited to 'deps/v8/src/torque/implementation-visitor.cc')
-rw-r--r-- | deps/v8/src/torque/implementation-visitor.cc | 773 |
1 files changed, 389 insertions, 384 deletions
diff --git a/deps/v8/src/torque/implementation-visitor.cc b/deps/v8/src/torque/implementation-visitor.cc index 2f2881fd07..00504b5eff 100644 --- a/deps/v8/src/torque/implementation-visitor.cc +++ b/deps/v8/src/torque/implementation-visitor.cc @@ -10,6 +10,7 @@ #include "src/base/optional.h" #include "src/common/globals.h" +#include "src/torque/cc-generator.h" #include "src/torque/constants.h" #include "src/torque/csa-generator.h" #include "src/torque/declaration-visitor.h" @@ -56,58 +57,136 @@ const Type* ImplementationVisitor::Visit(Statement* stmt) { return result; } -void ImplementationVisitor::BeginCSAFiles() { +void ImplementationVisitor::BeginGeneratedFiles() { + std::set<SourceId> contains_class_definitions; + for (const ClassType* type : TypeOracle::GetClasses()) { + if (type->GenerateCppClassDefinitions()) { + contains_class_definitions.insert(type->AttributedToFile()); + } + } + for (SourceId file : SourceFileMap::AllSources()) { - std::ostream& source = GlobalContext::GeneratedPerFile(file).csa_ccfile; - std::ostream& header = GlobalContext::GeneratedPerFile(file).csa_headerfile; + // Output beginning of CSA .cc file. + { + std::ostream& out = GlobalContext::GeneratedPerFile(file).csa_ccfile; - for (const std::string& include_path : GlobalContext::CppIncludes()) { - source << "#include " << StringLiteralQuote(include_path) << "\n"; - } + for (const std::string& include_path : GlobalContext::CppIncludes()) { + out << "#include " << StringLiteralQuote(include_path) << "\n"; + } - for (SourceId file : SourceFileMap::AllSources()) { - source << "#include \"torque-generated/" + - SourceFileMap::PathFromV8RootWithoutExtension(file) + - "-tq-csa.h\"\n"; - } - source << "\n"; - - source << "namespace v8 {\n" - << "namespace internal {\n" - << "\n"; - - std::string headerDefine = - "V8_GEN_TORQUE_GENERATED_" + - UnderlinifyPath(SourceFileMap::PathFromV8Root(file)) + "_H_"; - header << "#ifndef " << headerDefine << "\n"; - header << "#define " << headerDefine << "\n\n"; - header << "#include \"src/builtins/torque-csa-header-includes.h\"\n"; - header << "\n"; + for (SourceId file : SourceFileMap::AllSources()) { + out << "#include \"torque-generated/" + + SourceFileMap::PathFromV8RootWithoutExtension(file) + + "-tq-csa.h\"\n"; + } + out << "\n"; + + out << "namespace v8 {\n" + << "namespace internal {\n" + << "\n"; + } + // Output beginning of CSA .h file. + { + std::ostream& out = GlobalContext::GeneratedPerFile(file).csa_headerfile; + std::string headerDefine = + "V8_GEN_TORQUE_GENERATED_" + + UnderlinifyPath(SourceFileMap::PathFromV8Root(file)) + "_H_"; + out << "#ifndef " << headerDefine << "\n"; + out << "#define " << headerDefine << "\n\n"; + out << "#include \"src/builtins/torque-csa-header-includes.h\"\n"; + out << "\n"; + + out << "namespace v8 {\n" + << "namespace internal {\n" + << "\n"; + } + // Output beginning of class definition .cc file. + { + auto& streams = GlobalContext::GeneratedPerFile(file); + std::ostream& out = streams.class_definition_ccfile; + if (contains_class_definitions.count(file) != 0) { + out << "#include \"" + << SourceFileMap::PathFromV8RootWithoutExtension(file) + << "-inl.h\"\n\n"; + out << "#include \"torque-generated/class-verifiers.h\"\n"; + out << "#include \"src/objects/instance-type-inl.h\"\n\n"; + } - header << "namespace v8 {\n" - << "namespace internal {\n" - << "\n"; + out << "namespace v8 {\n"; + out << "namespace internal {\n"; + } } } -void ImplementationVisitor::EndCSAFiles() { +void ImplementationVisitor::EndGeneratedFiles() { for (SourceId file : SourceFileMap::AllSources()) { - std::ostream& source = GlobalContext::GeneratedPerFile(file).csa_ccfile; - std::ostream& header = GlobalContext::GeneratedPerFile(file).csa_headerfile; + { + std::ostream& out = GlobalContext::GeneratedPerFile(file).csa_ccfile; + + out << "} // namespace internal\n" + << "} // namespace v8\n" + << "\n"; + } + { + std::ostream& out = GlobalContext::GeneratedPerFile(file).csa_headerfile; - std::string headerDefine = - "V8_GEN_TORQUE_GENERATED_" + - UnderlinifyPath(SourceFileMap::PathFromV8Root(file)) + "_H_"; + std::string headerDefine = + "V8_GEN_TORQUE_GENERATED_" + + UnderlinifyPath(SourceFileMap::PathFromV8Root(file)) + "_H_"; + + out << "} // namespace internal\n" + << "} // namespace v8\n" + << "\n"; + out << "#endif // " << headerDefine << "\n"; + } + { + std::ostream& out = + GlobalContext::GeneratedPerFile(file).class_definition_ccfile; + + out << "} // namespace v8\n"; + out << "} // namespace internal\n"; + } + } +} - source << "} // namespace internal\n" - << "} // namespace v8\n" - << "\n"; +void ImplementationVisitor::BeginRuntimeMacrosFile() { + std::ostream& source = runtime_macros_cc_; + std::ostream& header = runtime_macros_h_; - header << "} // namespace internal\n" - << "} // namespace v8\n" - << "\n"; - header << "#endif // " << headerDefine << "\n"; + source << "#include \"torque-generated/runtime-macros.h\"\n\n"; + source << "#include \"src/torque/runtime-macro-shims.h\"\n"; + for (const std::string& include_path : GlobalContext::CppIncludes()) { + source << "#include " << StringLiteralQuote(include_path) << "\n"; } + source << "\n"; + + source << "namespace v8 {\n" + << "namespace internal {\n" + << "\n"; + + const char* kHeaderDefine = "V8_GEN_TORQUE_GENERATED_RUNTIME_MACROS_H_"; + header << "#ifndef " << kHeaderDefine << "\n"; + header << "#define " << kHeaderDefine << "\n\n"; + header << "#include \"src/builtins/torque-csa-header-includes.h\"\n"; + header << "\n"; + + header << "namespace v8 {\n" + << "namespace internal {\n" + << "\n"; +} + +void ImplementationVisitor::EndRuntimeMacrosFile() { + std::ostream& source = runtime_macros_cc_; + std::ostream& header = runtime_macros_h_; + + source << "} // namespace internal\n" + << "} // namespace v8\n" + << "\n"; + + header << "\n} // namespace internal\n" + << "} // namespace v8\n" + << "\n"; + header << "#endif // V8_GEN_TORQUE_GENERATED_RUNTIME_MACROS_H_\n"; } void ImplementationVisitor::Visit(NamespaceConstant* decl) { @@ -116,15 +195,15 @@ void ImplementationVisitor::Visit(NamespaceConstant* decl) { BindingsManagersScope bindings_managers_scope; - header_out() << " "; - GenerateFunctionDeclaration(header_out(), "", decl->external_name(), + csa_headerfile() << " "; + GenerateFunctionDeclaration(csa_headerfile(), "", decl->external_name(), signature, {}); - header_out() << ";\n"; + csa_headerfile() << ";\n"; - GenerateFunctionDeclaration(source_out(), "", decl->external_name(), + GenerateFunctionDeclaration(csa_ccfile(), "", decl->external_name(), signature, {}); - source_out() << " {\n"; - source_out() << " compiler::CodeAssembler ca_(state_);\n"; + csa_ccfile() << " {\n"; + csa_ccfile() << " compiler::CodeAssembler ca_(state_);\n"; DCHECK(!signature.return_type->IsVoidOrNever()); @@ -134,15 +213,15 @@ void ImplementationVisitor::Visit(NamespaceConstant* decl) { VisitResult return_result = GenerateImplicitConvert(signature.return_type, expression_result); - CSAGenerator csa_generator{assembler().Result(), source_out()}; + CSAGenerator csa_generator{assembler().Result(), csa_ccfile()}; Stack<std::string> values = *csa_generator.EmitGraph(Stack<std::string>{}); assembler_ = base::nullopt; - source_out() << " return "; - CSAGenerator::EmitCSAValue(return_result, values, source_out()); - source_out() << ";\n"; - source_out() << "}\n\n"; + csa_ccfile() << " return "; + CSAGenerator::EmitCSAValue(return_result, values, csa_ccfile()); + csa_ccfile() << ";\n"; + csa_ccfile() << "}\n\n"; } void ImplementationVisitor::Visit(TypeAlias* alias) { @@ -274,14 +353,21 @@ void ImplementationVisitor::VisitMacroCommon(Macro* macro) { bool has_return_value = can_return && return_type != TypeOracle::GetVoidType(); - GenerateMacroFunctionDeclaration(header_out(), "", macro); - header_out() << ";\n"; + GenerateMacroFunctionDeclaration(csa_headerfile(), macro); + csa_headerfile() << ";\n"; - GenerateMacroFunctionDeclaration(source_out(), "", macro); - source_out() << " {\n"; - source_out() << " compiler::CodeAssembler ca_(state_);\n"; - source_out() - << " compiler::CodeAssembler::SourcePositionScope pos_scope(&ca_);\n"; + GenerateMacroFunctionDeclaration(csa_ccfile(), macro); + csa_ccfile() << " {\n"; + + if (output_type_ == OutputType::kCC) { + // For now, generated C++ is only for field offset computations. If we ever + // generate C++ code that can allocate, then it should be handlified. + csa_ccfile() << " DisallowHeapAllocation no_gc;\n"; + } else { + csa_ccfile() << " compiler::CodeAssembler ca_(state_);\n"; + csa_ccfile() + << " compiler::CodeAssembler::SourcePositionScope pos_scope(&ca_);\n"; + } Stack<std::string> lowered_parameters; Stack<const Type*> lowered_parameter_types; @@ -363,18 +449,27 @@ void ImplementationVisitor::VisitMacroCommon(Macro* macro) { assembler().Bind(end); } - CSAGenerator csa_generator{assembler().Result(), source_out()}; - base::Optional<Stack<std::string>> values = - csa_generator.EmitGraph(lowered_parameters); + base::Optional<Stack<std::string>> values; + if (output_type_ == OutputType::kCC) { + CCGenerator cc_generator{assembler().Result(), csa_ccfile()}; + values = cc_generator.EmitGraph(lowered_parameters); + } else { + CSAGenerator csa_generator{assembler().Result(), csa_ccfile()}; + values = csa_generator.EmitGraph(lowered_parameters); + } assembler_ = base::nullopt; if (has_return_value) { - source_out() << " return "; - CSAGenerator::EmitCSAValue(return_value, *values, source_out()); - source_out() << ";\n"; + csa_ccfile() << " return "; + if (output_type_ == OutputType::kCC) { + CCGenerator::EmitCCValue(return_value, *values, csa_ccfile()); + } else { + CSAGenerator::EmitCSAValue(return_value, *values, csa_ccfile()); + } + csa_ccfile() << ";\n"; } - source_out() << "}\n\n"; + csa_ccfile() << "}\n\n"; } void ImplementationVisitor::Visit(TorqueMacro* macro) { @@ -416,7 +511,7 @@ void ImplementationVisitor::Visit(Builtin* builtin) { const std::string& name = builtin->ExternalName(); const Signature& signature = builtin->signature(); - source_out() << "TF_BUILTIN(" << name << ", CodeStubAssembler) {\n" + csa_ccfile() << "TF_BUILTIN(" << name << ", CodeStubAssembler) {\n" << " compiler::CodeAssemblerState* state_ = state();" << " compiler::CodeAssembler ca_(state());\n"; @@ -435,17 +530,17 @@ void ImplementationVisitor::Visit(Builtin* builtin) { .Position(signature.parameter_names[signature.implicit_count]->pos); } - source_out() - << " Node* argc = Parameter(Descriptor::kJSActualArgumentsCount);\n"; - source_out() << " TNode<IntPtrT> " + csa_ccfile() << " TNode<Word32T> argc = UncheckedParameter<Word32T>(" + << "Descriptor::kJSActualArgumentsCount);\n"; + csa_ccfile() << " TNode<IntPtrT> " "arguments_length(ChangeInt32ToIntPtr(UncheckedCast<" "Int32T>(argc)));\n"; - source_out() << " TNode<RawPtrT> arguments_frame = " + csa_ccfile() << " TNode<RawPtrT> arguments_frame = " "UncheckedCast<RawPtrT>(LoadFramePointer());\n"; - source_out() << " TorqueStructArguments " + csa_ccfile() << " TorqueStructArguments " "torque_arguments(GetFrameArguments(arguments_frame, " "arguments_length));\n"; - source_out() + csa_ccfile() << " CodeStubArguments arguments(this, torque_arguments);\n"; parameters.Push("torque_arguments.frame"); @@ -468,32 +563,32 @@ void ImplementationVisitor::Visit(Builtin* builtin) { const Type* actual_type = signature.parameter_types.types[i]; std::vector<const Type*> expected_types; if (param_name == "context") { - source_out() << " TNode<NativeContext> " << generated_name - << " = UncheckedCast<NativeContext>(Parameter(" - << "Descriptor::kContext));\n"; - source_out() << " USE(" << generated_name << ");\n"; + csa_ccfile() << " TNode<NativeContext> " << generated_name + << " = UncheckedParameter<NativeContext>(" + << "Descriptor::kContext);\n"; + csa_ccfile() << " USE(" << generated_name << ");\n"; expected_types = {TypeOracle::GetNativeContextType(), TypeOracle::GetContextType()}; } else if (param_name == "receiver") { - source_out() + csa_ccfile() << " TNode<Object> " << generated_name << " = " << (builtin->IsVarArgsJavaScript() ? "arguments.GetReceiver()" - : "UncheckedCast<Object>(Parameter(Descriptor::kReceiver))") + : "UncheckedParameter<Object>(Descriptor::kReceiver)") << ";\n"; - source_out() << "USE(" << generated_name << ");\n"; + csa_ccfile() << "USE(" << generated_name << ");\n"; expected_types = {TypeOracle::GetJSAnyType()}; } else if (param_name == "newTarget") { - source_out() << " TNode<Object> " << generated_name - << " = UncheckedCast<Object>(Parameter(" - << "Descriptor::kJSNewTarget));\n"; - source_out() << "USE(" << generated_name << ");\n"; + csa_ccfile() << " TNode<Object> " << generated_name + << " = UncheckedParameter<Object>(" + << "Descriptor::kJSNewTarget);\n"; + csa_ccfile() << "USE(" << generated_name << ");\n"; expected_types = {TypeOracle::GetJSAnyType()}; } else if (param_name == "target") { - source_out() << " TNode<JSFunction> " << generated_name - << " = UncheckedCast<JSFunction>(Parameter(" - << "Descriptor::kJSTarget));\n"; - source_out() << "USE(" << generated_name << ");\n"; + csa_ccfile() << " TNode<JSFunction> " << generated_name + << " = UncheckedParameter<JSFunction>(" + << "Descriptor::kJSTarget);\n"; + csa_ccfile() << "USE(" << generated_name << ");\n"; expected_types = {TypeOracle::GetJSFunctionType()}; } else { Error( @@ -519,12 +614,12 @@ void ImplementationVisitor::Visit(Builtin* builtin) { const bool mark_as_used = signature.implicit_count > i; std::string var = AddParameter(i, builtin, ¶meters, ¶meter_types, ¶meter_bindings, mark_as_used); - source_out() << " " << type->GetGeneratedTypeName() << " " << var + csa_ccfile() << " " << type->GetGeneratedTypeName() << " " << var << " = " - << "UncheckedCast<" << type->GetGeneratedTNodeTypeName() - << ">(Parameter(Descriptor::k" - << CamelifyString(parameter_name) << "));\n"; - source_out() << " USE(" << var << ");\n"; + << "UncheckedParameter<" << type->GetGeneratedTNodeTypeName() + << ">(Descriptor::k" << CamelifyString(parameter_name) + << ");\n"; + csa_ccfile() << " USE(" << var << ");\n"; } } else { @@ -536,18 +631,18 @@ void ImplementationVisitor::Visit(Builtin* builtin) { const bool mark_as_used = signature.implicit_count > i; std::string var = AddParameter(i, builtin, ¶meters, ¶meter_types, ¶meter_bindings, mark_as_used); - source_out() << " " << type->GetGeneratedTypeName() << " " << var + csa_ccfile() << " " << type->GetGeneratedTypeName() << " " << var << " = " - << "UncheckedCast<" << type->GetGeneratedTNodeTypeName() - << ">(Parameter("; + << "UncheckedParameter<" << type->GetGeneratedTNodeTypeName() + << ">("; if (i == 0 && has_context_parameter) { - source_out() << "Descriptor::kContext"; + csa_ccfile() << "Descriptor::kContext"; } else { - source_out() << "Descriptor::ParameterIndex<" + csa_ccfile() << "Descriptor::ParameterIndex<" << (has_context_parameter ? i - 1 : i) << ">()"; } - source_out() << "));\n"; - source_out() << " USE(" << var << ");\n"; + csa_ccfile() << ");\n"; + csa_ccfile() << " USE(" << var << ");\n"; } } assembler_ = CfgAssembler(parameter_types); @@ -555,11 +650,11 @@ void ImplementationVisitor::Visit(Builtin* builtin) { if (body_result != TypeOracle::GetNeverType()) { ReportError("control reaches end of builtin, expected return of a value"); } - CSAGenerator csa_generator{assembler().Result(), source_out(), + CSAGenerator csa_generator{assembler().Result(), csa_ccfile(), builtin->kind()}; csa_generator.EmitGraph(parameters); assembler_ = base::nullopt; - source_out() << "}\n\n"; + csa_ccfile() << "}\n\n"; } const Type* ImplementationVisitor::Visit(VarDeclarationStatement* stmt) { @@ -1255,53 +1350,20 @@ InitializerResults ImplementationVisitor::VisitInitializerResults( LocationReference ImplementationVisitor::GenerateFieldReference( VisitResult object, const Field& field, const ClassType* class_type) { + if (field.index.has_value()) { + return LocationReference::HeapSlice( + GenerateCall(class_type->GetSliceMacroName(field), {{object}, {}})); + } + DCHECK(field.offset.has_value()); StackRange result_range = assembler().TopRange(0); result_range.Extend(GenerateCopy(object).stack_range()); - VisitResult offset; - if (field.offset.has_value()) { - offset = - VisitResult(TypeOracle::GetConstInt31Type(), ToString(*field.offset)); - offset = GenerateImplicitConvert(TypeOracle::GetIntPtrType(), offset); - } else { - StackScope stack_scope(this); - for (const Field& f : class_type->ComputeAllFields()) { - if (f.offset) { - offset = - VisitResult(TypeOracle::GetConstInt31Type(), ToString(*f.offset)); - } - if (f.name_and_type.name == field.name_and_type.name) break; - if (f.index) { - if (!offset.IsOnStack()) { - offset = GenerateImplicitConvert(TypeOracle::GetIntPtrType(), offset); - } - VisitResult array_length = GenerateArrayLength(object, f); - size_t element_size; - std::string element_size_string; - std::tie(element_size, element_size_string) = - *SizeOf(f.name_and_type.type); - VisitResult array_element_size = - VisitResult(TypeOracle::GetConstInt31Type(), element_size_string); - // In contrast to the code used for allocation, we don't need overflow - // checks here because we already know all the offsets fit into memory. - VisitResult array_size = - GenerateCall("*", {{array_length, array_element_size}, {}}); - offset = GenerateCall("+", {{offset, array_size}, {}}); - } - } - DCHECK(offset.IsOnStack()); - offset = stack_scope.Yield(offset); - } + VisitResult offset = + VisitResult(TypeOracle::GetConstInt31Type(), ToString(*field.offset)); + offset = GenerateImplicitConvert(TypeOracle::GetIntPtrType(), offset); result_range.Extend(offset.stack_range()); - if (field.index) { - VisitResult length = GenerateArrayLength(object, field); - result_range.Extend(length.stack_range()); - const Type* slice_type = TypeOracle::GetSliceType(field.name_and_type.type); - return LocationReference::HeapSlice(VisitResult(slice_type, result_range)); - } else { - const Type* type = TypeOracle::GetReferenceType(field.name_and_type.type, - field.const_qualified); - return LocationReference::HeapReference(VisitResult(type, result_range)); - } + const Type* type = TypeOracle::GetReferenceType(field.name_and_type.type, + field.const_qualified); + return LocationReference::HeapReference(VisitResult(type, result_range)); } // This is used to generate field references during initialization, where we can @@ -1625,25 +1687,30 @@ VisitResult ImplementationVisitor::Visit(SpreadExpression* expr) { void ImplementationVisitor::GenerateImplementation(const std::string& dir) { for (SourceId file : SourceFileMap::AllSources()) { - std::string path_from_root = - SourceFileMap::PathFromV8RootWithoutExtension(file); - - std::string new_source( - GlobalContext::GeneratedPerFile(file).csa_ccfile.str()); + std::string base_filename = + dir + "/" + SourceFileMap::PathFromV8RootWithoutExtension(file); + GlobalContext::PerFileStreams& streams = + GlobalContext::GeneratedPerFile(file); - std::string source_file_name = dir + "/" + path_from_root + "-tq-csa.cc"; - WriteFile(source_file_name, new_source); - std::string new_header( - GlobalContext::GeneratedPerFile(file).csa_headerfile.str()); - std::string header_file_name = dir + "/" + path_from_root + "-tq-csa.h"; - WriteFile(header_file_name, new_header); + WriteFile(base_filename + "-tq-csa.cc", streams.csa_ccfile.str()); + WriteFile(base_filename + "-tq-csa.h", streams.csa_headerfile.str()); + WriteFile(base_filename + "-tq.inc", + streams.class_definition_headerfile.str()); + WriteFile(base_filename + "-tq-inl.inc", + streams.class_definition_inline_headerfile.str()); + WriteFile(base_filename + "-tq.cc", streams.class_definition_ccfile.str()); } + + WriteFile(dir + "/runtime-macros.h", runtime_macros_h_.str()); + WriteFile(dir + "/runtime-macros.cc", runtime_macros_cc_.str()); } -void ImplementationVisitor::GenerateMacroFunctionDeclaration( - std::ostream& o, const std::string& macro_prefix, Macro* macro) { - GenerateFunctionDeclaration(o, macro_prefix, macro->ExternalName(), - macro->signature(), macro->parameter_names()); +void ImplementationVisitor::GenerateMacroFunctionDeclaration(std::ostream& o, + Macro* macro) { + GenerateFunctionDeclaration( + o, "", + output_type_ == OutputType::kCC ? macro->CCName() : macro->ExternalName(), + macro->signature(), macro->parameter_names()); } std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration( @@ -1654,12 +1721,17 @@ std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration( if (signature.return_type->IsVoidOrNever()) { o << "void"; } else { - o << signature.return_type->GetGeneratedTypeName(); + o << (output_type_ == OutputType::kCC + ? signature.return_type->GetRuntimeType() + : signature.return_type->GetGeneratedTypeName()); } o << " " << macro_prefix << name << "("; bool first = true; - if (pass_code_assembler_state) { + if (output_type_ == OutputType::kCC) { + first = false; + o << "Isolate* isolate"; + } else if (pass_code_assembler_state) { first = false; o << "compiler::CodeAssemblerState* state_"; } @@ -1670,7 +1742,9 @@ std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration( first = false; const Type* parameter_type = signature.types()[i]; const std::string& generated_type_name = - parameter_type->GetGeneratedTypeName(); + output_type_ == OutputType::kCC + ? parameter_type->GetRuntimeType() + : parameter_type->GetGeneratedTypeName(); generated_parameter_names.push_back(ExternalParameterName( i < parameter_names.size() ? parameter_names[i]->value @@ -1679,6 +1753,9 @@ std::vector<std::string> ImplementationVisitor::GenerateFunctionDeclaration( } for (const LabelDeclaration& label_info : signature.labels) { + if (output_type_ == OutputType::kCC) { + ReportError("Macros that generate runtime code can't have label exits"); + } if (!first) o << ", "; first = false; generated_parameter_names.push_back( @@ -2487,7 +2564,7 @@ VisitResult ImplementationVisitor::GenerateCall( } } - bool inline_macro = callable->ShouldBeInlined(); + bool inline_macro = callable->ShouldBeInlined(output_type_); std::vector<VisitResult> implicit_arguments; for (size_t i = 0; i < callable->signature().implicit_count; ++i) { std::string implicit_name = callable->signature().parameter_names[i]->value; @@ -2594,7 +2671,18 @@ VisitResult ImplementationVisitor::GenerateCall( if (is_tailcall) { ReportError("can't tail call a macro"); } + macro->SetUsed(); + + // If we're currently generating a C++ macro and it's calling another macro, + // then we need to make sure that we also generate C++ code for the called + // macro. + if (output_type_ == OutputType::kCC && !inline_macro) { + if (auto* torque_macro = TorqueMacro::DynamicCast(macro)) { + GlobalContext::EnsureInCCOutputList(torque_macro); + } + } + if (return_type->IsConstexpr()) { DCHECK_EQ(0, arguments.labels.size()); std::stringstream result; @@ -2774,6 +2862,15 @@ VisitResult ImplementationVisitor::GenerateCall( result << constexpr_arguments[0]; result << ")"; return VisitResult(return_type, result.str()); + } else if (intrinsic->ExternalName() == "%IndexedFieldLength") { + const Type* type = specialization_types[0]; + const ClassType* class_type = ClassType::DynamicCast(type); + if (!class_type) { + ReportError("%IndexedFieldLength must take a class type parameter"); + } + const Field& field = + class_type->LookupField(StringLiteralUnquote(constexpr_arguments[0])); + return GenerateArrayLength(VisitResult(type, argument_range), field); } else { assembler().Emit(CallIntrinsicInstruction{intrinsic, specialization_types, constexpr_arguments}); @@ -3065,6 +3162,7 @@ void ImplementationVisitor::VisitAllDeclarables() { CurrentCallable::Scope current_callable(nullptr); const std::vector<std::unique_ptr<Declarable>>& all_declarables = GlobalContext::AllDeclarables(); + // This has to be an index-based loop because all_declarables can be extended // during the loop. for (size_t i = 0; i < all_declarables.size(); ++i) { @@ -3074,6 +3172,19 @@ void ImplementationVisitor::VisitAllDeclarables() { // Recover from compile errors here. The error is recorded already. } } + + // Do the same for macros which generate C++ code. + output_type_ = OutputType::kCC; + const std::vector<TorqueMacro*>& cc_macros = + GlobalContext::AllMacrosForCCOutput(); + for (size_t i = 0; i < cc_macros.size(); ++i) { + try { + Visit(static_cast<Declarable*>(cc_macros[i])); + } catch (TorqueAbortCompilation&) { + // Recover from compile errors here. The error is recorded already. + } + } + output_type_ = OutputType::kCSA; } void ImplementationVisitor::Visit(Declarable* declarable) { @@ -3082,7 +3193,7 @@ void ImplementationVisitor::Visit(Declarable* declarable) { CurrentFileStreams::Scope current_file_streams( &GlobalContext::GeneratedPerFile(declarable->Position().source)); if (Callable* callable = Callable::DynamicCast(declarable)) { - if (!callable->ShouldGenerateExternalCode()) + if (!callable->ShouldGenerateExternalCode(output_type_)) CurrentFileStreams::Get() = nullptr; } switch (declarable->kind()) { @@ -3605,6 +3716,17 @@ base::Optional<std::vector<Field>> GetOrderedUniqueIndexFields( } void CppClassGenerator::GenerateClass() { + hdr_ << "\n"; + hdr_ << "// Alias for HeapObject::Is" << name_ + << "() that avoids inlining.\n"; + hdr_ << "V8_EXPORT_PRIVATE bool Is" << name_ << "_NonInline(HeapObject o);\n"; + hdr_ << "\n"; + + impl_ << "\n"; + impl_ << "bool Is" << name_ << "_NonInline(HeapObject o) {\n"; + impl_ << " return o.Is" << name_ << "();\n"; + impl_ << "}\n\n"; + hdr_ << template_decl() << "\n"; hdr_ << "class " << gen_name_ << " : public P {\n"; hdr_ << " static_assert(std::is_same<" << name_ << ", D>::value,\n" @@ -3707,7 +3829,7 @@ void CppClassGenerator::GenerateClass() { hdr_ << "};\n\n"; - if (!type_->IsExtern()) { + if (type_->ShouldGenerateFullClassDefinition()) { GenerateClassExport(type_, hdr_, inl_); } } @@ -3732,7 +3854,7 @@ void CppClassGenerator::GenerateClassConstructors() { << name_ << ".\");\n"; hdr_ << " }\n"; - hdr_ << "protected:\n"; + hdr_ << " protected:\n"; hdr_ << " inline explicit " << gen_name_ << "(Address ptr);\n"; hdr_ << " // Special-purpose constructor for subclasses that have fast " "paths where\n"; @@ -3743,16 +3865,17 @@ void CppClassGenerator::GenerateClassConstructors() { inl_ << "template<class D, class P>\n"; inl_ << "inline " << gen_name_T_ << "::" << gen_name_ << "(Address ptr)\n"; inl_ << " : P(ptr) {\n"; - inl_ << " SLOW_DCHECK(this->Is" << name_ << "());\n"; + inl_ << " SLOW_DCHECK(Is" << name_ << "_NonInline(*this));\n"; inl_ << "}\n"; inl_ << "template<class D, class P>\n"; inl_ << "inline " << gen_name_T_ << "::" << gen_name_ << "(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi)\n"; inl_ << " : P(ptr, allow_smi) {\n"; - inl_ << " SLOW_DCHECK((allow_smi == " - "HeapObject::AllowInlineSmiStorage::kAllowBeingASmi && " - << "this->IsSmi()) || this->Is" << name_ << "());\n"; + inl_ << " SLOW_DCHECK(" + << "(allow_smi == HeapObject::AllowInlineSmiStorage::kAllowBeingASmi" + " && this->IsSmi()) || Is" + << name_ << "_NonInline(*this));\n"; inl_ << "}\n"; } @@ -3767,15 +3890,15 @@ std::string GenerateRuntimeTypeCheck(const Type* type, type_check << value << ".IsCleared()"; at_start = false; } - for (const RuntimeType& runtime_type : type->GetRuntimeTypes()) { + for (const TypeChecker& runtime_type : type->GetTypeCheckers()) { if (!at_start) type_check << " || "; at_start = false; if (maybe_object) { bool strong = runtime_type.weak_ref_to.empty(); - if (strong && runtime_type.type == "MaybeObject") { - // Rather than a generic Weak<T>, this is a basic type Tagged or - // WeakHeapObject. We can't validate anything more about the type of - // the object pointed to, so just check that it's weak. + if (strong && runtime_type.type == WEAK_HEAP_OBJECT) { + // Rather than a generic Weak<T>, this is the basic type WeakHeapObject. + // We can't validate anything more about the type of the object pointed + // to, so just check that it's weak. type_check << value << ".IsWeak()"; } else { type_check << "(" << (strong ? "!" : "") << value << ".IsWeak() && " @@ -3954,7 +4077,7 @@ void CppClassGenerator::GenerateFieldAccessorForTagged(const Field& f) { std::string offset = "k" + CamelifyString(name) + "Offset"; bool strong_pointer = field_type->IsSubtypeOf(TypeOracle::GetObjectType()); - std::string type = field_type->GetRuntimeType(); + std::string type = field_type->UnhandlifiedCppTypeName(); // Generate declarations in header. if (!field_type->IsClassType() && field_type != TypeOracle::GetObjectType()) { hdr_ << " // Torque type: " << field_type->ToString() << "\n"; @@ -3962,7 +4085,7 @@ void CppClassGenerator::GenerateFieldAccessorForTagged(const Field& f) { hdr_ << " inline " << type << " " << name << "(" << (f.index ? "int i" : "") << ") const;\n"; - hdr_ << " inline " << type << " " << name << "(const Isolate* isolates" + hdr_ << " inline " << type << " " << name << "(IsolateRoot isolates" << (f.index ? ", int i" : "") << ") const;\n"; hdr_ << " inline void set_" << name << "(" << (f.index ? "int i, " : "") << type << " value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);\n\n"; @@ -3973,15 +4096,14 @@ void CppClassGenerator::GenerateFieldAccessorForTagged(const Field& f) { inl_ << "template <class D, class P>\n"; inl_ << type << " " << gen_name_ << "<D, P>::" << name << "(" << (f.index ? "int i" : "") << ") const {\n"; - inl_ << " const Isolate* isolate = GetIsolateForPtrCompr(*this);\n"; + inl_ << " IsolateRoot isolate = GetIsolateForPtrCompr(*this);\n"; inl_ << " return " << gen_name_ << "::" << name << "(isolate" << (f.index ? ", i" : "") << ");\n"; inl_ << "}\n"; inl_ << "template <class D, class P>\n"; inl_ << type << " " << gen_name_ << "<D, P>::" << name - << "(const Isolate* isolate" << (f.index ? ", int i" : "") - << ") const {\n"; + << "(IsolateRoot isolate" << (f.index ? ", int i" : "") << ") const {\n"; // TODO(tebbi): The distinction between relaxed and non-relaxed accesses here // is pretty arbitrary and just tries to preserve what was there before. @@ -4031,35 +4153,6 @@ void CppClassGenerator::GenerateFieldAccessorForTagged(const Field& f) { inl_ << "}\n\n"; } -void EmitClassDefinitionHeadersIncludes(const std::string& basename, - std::stringstream& header, - std::stringstream& inline_header) { - header << "#include \"src/objects/objects.h\"\n"; - header << "#include \"src/objects/heap-object.h\"\n"; - header << "#include \"src/objects/smi.h\"\n"; - header << "#include \"torque-generated/field-offsets.h\"\n"; - header << "#include <type_traits>\n\n"; - - inline_header << "#include \"torque-generated/class-definitions.h\"\n"; - inline_header << "#include \"src/objects/js-function.h\"\n"; - inline_header << "#include \"src/objects/js-objects.h\"\n"; - inline_header << "#include \"src/objects/js-promise.h\"\n"; - inline_header << "#include \"src/objects/js-weak-refs.h\"\n"; - inline_header << "#include \"src/objects/module.h\"\n"; - inline_header << "#include \"src/objects/objects-inl.h\"\n"; - inline_header << "#include \"src/objects/script.h\"\n"; - inline_header << "#include \"src/objects/shared-function-info.h\"\n"; - inline_header << "#include \"src/objects/tagged-field.h\"\n\n"; -} - -void EmitClassDefinitionHeadersForwardDeclarations(std::stringstream& header) { - // Generate forward declarations for every class. - for (const ClassType* type : TypeOracle::GetClasses()) { - header << "class " << type->GetGeneratedTNodeTypeName() << ";\n"; - } - header << "using BuiltinPtr = Smi;\n\n"; -} - void GenerateStructLayoutDescription(std::ostream& header, const StructType* type) { header << "struct TorqueGenerated" << CamelifyString(type->name()) @@ -4077,125 +4170,45 @@ void GenerateStructLayoutDescription(std::ostream& header, void ImplementationVisitor::GenerateClassDefinitions( const std::string& output_directory) { - std::stringstream external_header; - std::stringstream inline_external_header; - std::stringstream internal_header; - std::stringstream inline_internal_header; - std::stringstream exported_header; - std::stringstream inline_exported_header; - std::stringstream implementation; std::stringstream factory_header; std::stringstream factory_impl; - std::string basename = "class-definitions"; - std::string internal_basename = "internal-" + basename; - std::string exported_basename = "exported-" + basename; - std::string file_basename = output_directory + "/" + basename; - std::string internal_file_basename = - output_directory + "/" + internal_basename; - std::string exported_file_basename = - output_directory + "/" + exported_basename; std::string factory_basename = "factory"; - std::string factory_file_basename = output_directory + "/" + factory_basename; - - { - IncludeGuardScope header_guard(external_header, basename + ".h"); - - IncludeGuardScope inline_header_guard(inline_external_header, - basename + "-inl.h"); - - IncludeGuardScope internal_header_guard(internal_header, - internal_basename + ".h"); - - IncludeGuardScope internal_inline_header_guard( - inline_internal_header, internal_basename + "-inl.h"); - - IncludeGuardScope exported_header_guard(exported_header, - exported_basename + ".h"); - - IncludeGuardScope exported_inline_header_guard( - inline_exported_header, exported_basename + "-inl.h"); - - internal_header << "#include \"torque-generated/class-definitions.h\"\n"; - internal_header << "#include \"src/objects/fixed-array.h\"\n"; - inline_internal_header - << "#include \"torque-generated/internal-class-definitions.h\"\n"; - inline_internal_header - << "#include \"torque-generated/class-definitions-inl.h\"\n"; - - exported_header << "#include \"src/objects/fixed-array.h\"\n"; - exported_header << "#include \"torque-generated/class-definitions.h\"\n"; - inline_exported_header - << "#include \"torque-generated/exported-class-definitions.h\"\n"; - inline_exported_header << "#include \"src/objects/fixed-array-inl.h\"\n"; - - EmitClassDefinitionHeadersIncludes(basename, external_header, - inline_external_header); - - EmitClassDefinitionHeadersIncludes(internal_basename, internal_header, - inline_internal_header); - - IncludeObjectMacrosScope header_macros(external_header); - IncludeObjectMacrosScope inline_header_macros(inline_external_header); - - IncludeObjectMacrosScope internal_header_macros(internal_header); - IncludeObjectMacrosScope internal_inline_header_macros( - inline_internal_header); - IncludeObjectMacrosScope exported_header_macros(exported_header); - IncludeObjectMacrosScope exported_inline_header_macros( - inline_exported_header); - - NamespaceScope header_namespaces(external_header, {"v8", "internal"}); - NamespaceScope inline_header_namespaces(inline_external_header, - {"v8", "internal"}); - NamespaceScope internal_header_namespaces(internal_header, - {"v8", "internal"}); - NamespaceScope internal_inline_header_namespaces(inline_internal_header, - {"v8", "internal"}); - NamespaceScope exported_header_namespaces(exported_header, - {"v8", "internal"}); - NamespaceScope exported_inline_header_namespaces(inline_exported_header, - {"v8", "internal"}); - - EmitClassDefinitionHeadersForwardDeclarations(external_header); - EmitClassDefinitionHeadersForwardDeclarations(internal_header); + std::stringstream forward_declarations; + std::string forward_declarations_filename = "class-forward-declarations.h"; + { factory_impl << "#include \"src/heap/factory.h\"\n"; factory_impl << "#include \"src/heap/factory-inl.h\"\n"; factory_impl << "#include \"src/heap/heap.h\"\n"; factory_impl << "#include \"src/heap/heap-inl.h\"\n"; - factory_impl << "#include \"src/execution/isolate.h\"\n\n"; - factory_impl << "#include " - "\"torque-generated/internal-class-definitions-inl.h\"\n\n"; + factory_impl << "#include \"src/execution/isolate.h\"\n"; factory_impl << "#include " - "\"torque-generated/exported-class-definitions-inl.h\"\n\n"; + "\"src/objects/all-objects-inl.h\"\n\n"; NamespaceScope factory_impl_namespaces(factory_impl, {"v8", "internal"}); factory_impl << "\n"; - implementation << "#include \"torque-generated/class-definitions.h\"\n\n"; - implementation << "#include \"torque-generated/class-verifiers.h\"\n\n"; - implementation - << "#include \"src/objects/class-definitions-tq-deps-inl.h\"\n\n"; - implementation - << "#include " - "\"torque-generated/internal-class-definitions-inl.h\"\n\n"; - implementation - << "#include " - "\"torque-generated/exported-class-definitions-inl.h\"\n\n"; - NamespaceScope implementation_namespaces(implementation, - {"v8", "internal"}); + IncludeGuardScope include_guard(forward_declarations, + forward_declarations_filename); + NamespaceScope forward_declarations_namespaces(forward_declarations, + {"v8", "internal"}); std::set<const StructType*, TypeLess> structs_used_in_classes; + // Emit forward declarations. + for (const ClassType* type : TypeOracle::GetClasses()) { + auto& streams = GlobalContext::GeneratedPerFile(type->AttributedToFile()); + std::ostream& header = streams.class_definition_headerfile; + header << "class " << type->GetGeneratedTNodeTypeName() << ";\n"; + forward_declarations << "class " << type->GetGeneratedTNodeTypeName() + << ";\n"; + } + for (const ClassType* type : TypeOracle::GetClasses()) { - std::stringstream& header = - type->IsExtern() - ? external_header - : type->ShouldExport() ? exported_header : internal_header; - std::stringstream& inline_header = - type->IsExtern() ? inline_external_header - : type->ShouldExport() ? inline_exported_header - : inline_internal_header; + auto& streams = GlobalContext::GeneratedPerFile(type->AttributedToFile()); + std::ostream& header = streams.class_definition_headerfile; + std::ostream& inline_header = streams.class_definition_inline_headerfile; + std::ostream& implementation = streams.class_definition_ccfile; if (type->GenerateCppClassDefinitions()) { CppClassGenerator g(type, header, inline_header, implementation); @@ -4207,7 +4220,8 @@ void ImplementationVisitor::GenerateClassDefinitions( structs_used_in_classes.insert(*field_as_struct); } } - if (type->ShouldExport() && !type->IsAbstract()) { + if (type->ShouldExport() && !type->IsAbstract() && + !type->HasCustomMap()) { factory_header << type->HandlifiedCppTypeName() << " New" << type->name() << "("; factory_impl << type->HandlifiedCppTypeName() << " Factory::New" @@ -4251,9 +4265,12 @@ void ImplementationVisitor::GenerateClassDefinitions( factory_impl << " " "isolate()->heap()->AllocateRawWith<Heap::kRetryOrFail>" "(size, allocation_type);\n"; + factory_impl << " WriteBarrierMode write_barrier_mode =\n" + << " allocation_type == AllocationType::kYoung\n" + << " ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;\n"; factory_impl << " result.set_map_after_allocation(roots." << SnakeifyString(type->name()) - << "_map(), SKIP_WRITE_BARRIER);\n"; + << "_map(), write_barrier_mode);\n"; factory_impl << " " << type->HandlifiedCppTypeName() << " result_handle(" << type->name() << "::cast(result), isolate());\n"; @@ -4267,7 +4284,7 @@ void ImplementationVisitor::GenerateClassDefinitions( TypeOracle::GetTaggedType()) && !f.name_and_type.type->IsSubtypeOf(TypeOracle::GetSmiType())) { factory_impl << "*" << f.name_and_type.name - << ", SKIP_WRITE_BARRIER"; + << ", write_barrier_mode"; } else { factory_impl << f.name_and_type.name; } @@ -4281,20 +4298,20 @@ void ImplementationVisitor::GenerateClassDefinitions( } for (const StructType* type : structs_used_in_classes) { + std::ostream& header = + GlobalContext::GeneratedPerFile(type->GetPosition().source) + .class_definition_headerfile; if (type != TypeOracle::GetFloat64OrHoleType()) { - GenerateStructLayoutDescription(external_header, type); + GenerateStructLayoutDescription(header, type); } } } - WriteFile(file_basename + ".h", external_header.str()); - WriteFile(file_basename + "-inl.h", inline_external_header.str()); - WriteFile(file_basename + ".cc", implementation.str()); - WriteFile(internal_file_basename + ".h", internal_header.str()); - WriteFile(internal_file_basename + "-inl.h", inline_internal_header.str()); - WriteFile(exported_file_basename + ".h", exported_header.str()); - WriteFile(exported_file_basename + "-inl.h", inline_exported_header.str()); - WriteFile(factory_file_basename + ".inc", factory_header.str()); - WriteFile(factory_file_basename + ".cc", factory_impl.str()); + WriteFile(output_directory + "/" + factory_basename + ".inc", + factory_header.str()); + WriteFile(output_directory + "/" + factory_basename + ".cc", + factory_impl.str()); + WriteFile(output_directory + "/" + forward_declarations_filename, + forward_declarations.str()); } namespace { @@ -4305,7 +4322,7 @@ void GeneratePrintDefinitionsForClass(std::ostream& impl, const ClassType* type, impl << template_params << "\n"; impl << "void " << gen_name_T << "::" << type->name() << "Print(std::ostream& os) {\n"; - impl << " this->PrintHeader(os, \"" << gen_name << "\");\n"; + impl << " this->PrintHeader(os, \"" << type->name() << "\");\n"; auto hierarchy = type->GetHierarchy(); std::map<std::string, const AggregateType*> field_names; for (const AggregateType* aggregate_type : hierarchy) { @@ -4340,14 +4357,8 @@ void ImplementationVisitor::GeneratePrintDefinitions( { IfDefScope object_print(impl, "OBJECT_PRINT"); - impl << "#include \"src/objects/objects.h\"\n\n"; impl << "#include <iosfwd>\n\n"; - impl << "#include " - "\"torque-generated/internal-class-definitions-inl.h\"\n"; - impl << "#include " - "\"torque-generated/exported-class-definitions-inl.h\"\n"; - impl << "#include \"src/objects/struct-inl.h\"\n\n"; - impl << "#include \"src/objects/template-objects-inl.h\"\n\n"; + impl << "#include \"src/objects/all-objects-inl.h\"\n\n"; NamespaceScope impl_namespaces(impl, {"v8", "internal"}); @@ -4532,8 +4543,10 @@ void ImplementationVisitor::GenerateBodyDescriptors( if (type->size().SingleValue()) { h_contents << " return " << *type->size().SingleValue() << ";\n"; } else { + // We use an unchecked_cast here because this is used for concurrent + // marking, where we shouldn't re-read the map. h_contents << " return " << name - << "::cast(raw_object).AllocatedSize();\n"; + << "::unchecked_cast(raw_object).AllocatedSize();\n"; } h_contents << " }\n\n"; @@ -4548,10 +4561,9 @@ namespace { // Generate verification code for a single piece of class data, which might be // nested within a struct or might be a single element in an indexed field (or // both). -void GenerateFieldValueVerifier(const std::string& class_name, - const Field& class_field, - const Field& leaf_field, size_t struct_offset, - std::string field_size, +void GenerateFieldValueVerifier(const std::string& class_name, bool indexed, + std::string offset, const Field& leaf_field, + std::string indexed_field_size, std::ostream& cc_contents) { const Type* field_type = leaf_field.name_and_type.type; @@ -4560,17 +4572,15 @@ void GenerateFieldValueVerifier(const std::string& class_name, const char* object_type = maybe_object ? "MaybeObject" : "Object"; const char* verify_fn = maybe_object ? "VerifyMaybeObjectPointer" : "VerifyPointer"; - std::string index_offset = std::to_string(struct_offset); - if (class_field.index) { - index_offset += " + i * " + field_size; + if (indexed) { + offset += " + i * " + indexed_field_size; } // Name the local var based on the field name for nicer CHECK output. const std::string value = leaf_field.name_and_type.name + "__value"; // Read the field. cc_contents << " " << object_type << " " << value << " = TaggedField<" - << object_type << ", " << *class_field.offset << ">::load(o, " - << index_offset << ");\n"; + << object_type << ">::load(o, " << offset << ");\n"; // Call VerifyPointer or VerifyMaybeObjectPointer on it. cc_contents << " " << object_type << "::" << verify_fn << "(isolate, " @@ -4601,49 +4611,49 @@ void GenerateClassFieldVerifier(const std::string& class_name, // Do not verify if the field may be uninitialized. if (TypeOracle::GetUninitializedType()->IsSubtypeOf(field_type)) return; + std::string field_start_offset; if (f.index) { - base::Optional<NameAndType> array_length = - ExtractSimpleFieldArraySize(class_type, *f.index); - if (!array_length) { - Error("Cannot generate verifier for array field with complex length.") - .Position((*f.index)->pos) - .Throw(); - } - - std::string length_field_offset = - class_name + "::k" + CamelifyString(array_length->name) + "Offset"; - cc_contents << " for (int i = 0; i < "; - if (array_length->type == TypeOracle::GetSmiType()) { - // We already verified the index field because it was listed earlier, so - // we can assume it's safe to read here. - cc_contents << "TaggedField<Smi, " << length_field_offset - << ">::load(o).value()"; - } else { - const Type* constexpr_version = array_length->type->ConstexprVersion(); - if (constexpr_version == nullptr) { - Error("constexpr representation for type ", - array_length->type->ToString(), - " is required due to usage as index") - .Position(f.pos); - } - cc_contents << "o.ReadField<" << constexpr_version->GetGeneratedTypeName() - << ">(" << length_field_offset << ")"; - } - cc_contents << "; ++i) {\n"; + field_start_offset = f.name_and_type.name + "__offset"; + std::string length = f.name_and_type.name + "__length"; + cc_contents << " intptr_t " << field_start_offset << ", " << length + << ";\n"; + cc_contents << " std::tie(std::ignore, " << field_start_offset << ", " + << length << ") = " + << Callable::PrefixNameForCCOutput( + class_type.GetSliceMacroName(f)) + << "(isolate, o);\n"; + + // Slices use intptr, but TaggedField<T>.load() uses int, so verify that + // such a cast is valid. + cc_contents << " CHECK_EQ(" << field_start_offset << ", static_cast<int>(" + << field_start_offset << "));\n"; + cc_contents << " CHECK_EQ(" << length << ", static_cast<int>(" << length + << "));\n"; + field_start_offset = "static_cast<int>(" + field_start_offset + ")"; + length = "static_cast<int>(" + length + ")"; + + cc_contents << " for (int i = 0; i < " << length << "; ++i) {\n"; } else { + // Non-indexed fields have known offsets. + field_start_offset = std::to_string(*f.offset); cc_contents << " {\n"; } if (auto struct_type = field_type->StructSupertype()) { - for (const Field& field : (*struct_type)->fields()) { - if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { - GenerateFieldValueVerifier(class_name, f, field, *field.offset, - std::to_string((*struct_type)->PackedSize()), - cc_contents); + for (const Field& struct_field : (*struct_type)->fields()) { + if (struct_field.name_and_type.type->IsSubtypeOf( + TypeOracle::GetTaggedType())) { + GenerateFieldValueVerifier( + class_name, f.index.has_value(), + field_start_offset + " + " + std::to_string(*struct_field.offset), + struct_field, std::to_string((*struct_type)->PackedSize()), + cc_contents); } } } else { - GenerateFieldValueVerifier(class_name, f, f, 0, "kTaggedSize", cc_contents); + GenerateFieldValueVerifier(class_name, f.index.has_value(), + field_start_offset, f, "kTaggedSize", + cc_contents); } cc_contents << " }\n"; @@ -4668,9 +4678,8 @@ void ImplementationVisitor::GenerateClassVerifiers( } cc_contents << "#include \"torque-generated/" << file_name << ".h\"\n"; cc_contents << "#include " - "\"torque-generated/internal-class-definitions-inl.h\"\n"; - cc_contents << "#include " - "\"torque-generated/exported-class-definitions-inl.h\"\n"; + "\"src/objects/all-objects-inl.h\"\n"; + cc_contents << "#include \"torque-generated/runtime-macros.h\"\n"; IncludeObjectMacrosScope object_macros(cc_contents); @@ -4781,10 +4790,6 @@ void ImplementationVisitor::GenerateExportedMacrosAssembler( h_contents << "#include \"src/compiler/code-assembler.h\"\n"; h_contents << "#include \"src/execution/frames.h\"\n"; h_contents << "#include \"torque-generated/csa-types.h\"\n"; - h_contents - << "#include \"torque-generated/internal-class-definitions.h\"\n"; - h_contents - << "#include \"torque-generated/exported-class-definitions.h\"\n"; cc_contents << "#include \"src/objects/fixed-array-inl.h\"\n"; cc_contents << "#include \"src/objects/free-space.h\"\n"; cc_contents << "#include \"src/objects/js-regexp-string-iterator.h\"\n"; |