[torque] allow builtins without context parameter

Bug: v8:10404, v8:7793
Change-Id: I7ed5fc790bd97af0dd3671669779e416101731ce
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2162877
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67435}
This commit is contained in:
Tobias Tebbi 2020-04-28 14:27:43 +02:00 committed by Commit Bot
parent 2ce3a8e973
commit b5ab5c7b75
12 changed files with 108 additions and 78 deletions

View File

@ -494,9 +494,9 @@ extern transitioning macro ToThisValue(implicit context: Context)(
extern transitioning macro GetProperty(implicit context: Context)(
JSAny, JSAny): JSAny;
extern transitioning builtin SetProperty(implicit context: Context)(
JSAny, JSAny, JSAny);
JSAny, JSAny, JSAny): JSAny;
extern transitioning builtin SetPropertyInLiteral(implicit context: Context)(
JSAny, JSAny, JSAny);
JSAny, JSAny, JSAny): JSAny;
extern transitioning builtin DeleteProperty(implicit context: Context)(
JSAny, JSAny | PrivateSymbol, LanguageModeSmi): Boolean;
extern transitioning builtin HasProperty(implicit context: Context)(

View File

@ -46,8 +46,6 @@ namespace iterator {
extern macro IteratorBuiltinsAssembler::StringListFromIterable(
implicit context: Context)(JSAny): JSArray;
extern builtin IterableToListMayPreserveHoles(implicit context:
Context)(JSAny, JSAny);
extern builtin IterableToListWithSymbolLookup(implicit context:
Context)(JSAny): JSArray;
extern builtin IterableToFixedArrayWithSymbolLookupSlow(

View File

@ -127,7 +127,7 @@ namespace typed_array {
const work2: FixedArray = AllocateZeroedFixedArray(Convert<intptr>(len));
for (let i: uintptr = 0; i < len; ++i) {
const element: Numeric = accessor.LoadNumeric(context, array, i);
const element: Numeric = accessor.LoadNumeric(array, i);
work1.objects[i] = element;
work2.objects[i] = element;
}

View File

@ -81,7 +81,7 @@ namespace typed_array {
Context, JSTypedArray, uintptr, JSAny,
constexpr ElementsKind) labels IfDetached;
type LoadNumericFn = builtin(Context, JSTypedArray, uintptr) => Numeric;
type LoadNumericFn = builtin(JSTypedArray, uintptr) => Numeric;
type StoreNumericFn = builtin(Context, JSTypedArray, uintptr, Numeric) => Smi;
type StoreJSAnyFn = builtin(Context, JSTypedArray, uintptr, JSAny) => Smi;
@ -90,10 +90,9 @@ namespace typed_array {
const kStoreFailureArrayDetached: Smi = 1;
struct TypedArrayAccessor {
macro LoadNumeric(
context: Context, array: JSTypedArray, index: uintptr): Numeric {
macro LoadNumeric(array: JSTypedArray, index: uintptr): Numeric {
const loadfn: LoadNumericFn = this.loadNumericFn;
return loadfn(context, array, index);
return loadfn(array, index);
}
macro StoreNumeric(
@ -189,7 +188,7 @@ namespace typed_array {
macro Load(implicit context: Context)(k: uintptr): JSAny {
const lf: LoadNumericFn = this.loadfn;
return lf(context, this.unstable, k);
return lf(this.unstable, k);
}
stable: JSTypedArray;
@ -245,7 +244,7 @@ namespace typed_array {
}
builtin LoadTypedElement<T : type extends ElementsKind>(
_context: Context, array: JSTypedArray, index: uintptr): Numeric {
array: JSTypedArray, index: uintptr): Numeric {
return LoadFixedTypedArrayElementAsTagged(
array.data_ptr, index, KindForArrayType<T>());
}

View File

@ -520,10 +520,12 @@ class V8_EXPORT_PRIVATE VoidDescriptor : public CallInterfaceDescriptor {
};
// This class is subclassed by Torque-generated call interface descriptors.
template <int parameter_count>
template <int parameter_count, bool has_context_parameter>
class TorqueInterfaceDescriptor : public CallInterfaceDescriptor {
public:
static constexpr int kDescriptorFlags = CallInterfaceDescriptorData::kNoFlags;
static constexpr int kDescriptorFlags =
has_context_parameter ? CallInterfaceDescriptorData::kNoFlags
: CallInterfaceDescriptorData::kNoContext;
static constexpr int kParameterCount = parameter_count;
enum ParameterIndices { kContext = kParameterCount };
template <int i>

View File

@ -512,8 +512,14 @@ void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction,
LowerType(instruction.builtin->signature().return_type);
if (instruction.is_tailcall) {
out() << " CodeStubAssembler(state_).TailCallBuiltin(Builtins::k"
<< instruction.builtin->ExternalName() << ", ";
PrintCommaSeparatedList(out(), arguments);
<< instruction.builtin->ExternalName();
if (!instruction.builtin->signature().HasContextParameter()) {
// Add dummy context parameter to satisfy the TailCallBuiltin signature.
out() << ", TNode<Object>()";
}
for (const std::string& argument : arguments) {
out() << ", " << argument;
}
out() << ");\n";
} else {
std::string result_name;
@ -525,25 +531,24 @@ void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction,
std::string catch_name =
PreCallableExceptionPreparation(instruction.catch_block);
Stack<std::string> pre_call_stack = *stack;
if (result_types.size() == 1) {
std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
stack->Push(result_name);
out() << " " << result_name << " = ";
if (generated_type != "Object") out() << "TORQUE_CAST(";
out() << "CodeStubAssembler(state_).CallBuiltin(Builtins::k"
<< instruction.builtin->ExternalName() << ", ";
PrintCommaSeparatedList(out(), arguments);
if (generated_type != "Object") out() << ")";
out() << ");\n";
} else {
DCHECK_EQ(0, result_types.size());
// TODO(tebbi): Actually, builtins have to return a value, so we should
// not have to handle this case.
out() << " CodeStubAssembler(state_).CallBuiltin(Builtins::k"
<< instruction.builtin->ExternalName() << ", ";
PrintCommaSeparatedList(out(), arguments);
out() << ");\n";
DCHECK_EQ(1, result_types.size());
std::string generated_type = result_types[0]->GetGeneratedTNodeTypeName();
stack->Push(result_name);
out() << " " << result_name << " = ";
if (generated_type != "Object") out() << "TORQUE_CAST(";
out() << "CodeStubAssembler(state_).CallBuiltin(Builtins::k"
<< instruction.builtin->ExternalName();
if (!instruction.builtin->signature().HasContextParameter()) {
// Add dummy context parameter to satisfy the CallBuiltin signature.
out() << ", TNode<Object>()";
}
for (const std::string& argument : arguments) {
out() << ", " << argument;
}
if (generated_type != "Object") out() << ")";
out() << ");\n";
PostCallableExceptionPreparation(
catch_name,
result_types.size() == 0 ? TypeOracle::GetVoidType() : result_types[0],
@ -555,8 +560,8 @@ void CSAGenerator::EmitInstruction(const CallBuiltinInstruction& instruction,
void CSAGenerator::EmitInstruction(
const CallBuiltinPointerInstruction& instruction,
Stack<std::string>* stack) {
std::vector<std::string> function_and_arguments =
stack->PopMany(1 + instruction.argc);
std::vector<std::string> arguments = stack->PopMany(instruction.argc);
std::string function = stack->Pop();
std::vector<const Type*> result_types =
LowerType(instruction.type->return_type());
if (result_types.size() != 1) {
@ -576,8 +581,15 @@ void CSAGenerator::EmitInstruction(
"CallableFor(ca_."
"isolate(),"
"ExampleBuiltinForTorqueFunctionPointerType("
<< instruction.type->function_pointer_type_id() << ")).descriptor(), ";
PrintCommaSeparatedList(out(), function_and_arguments);
<< instruction.type->function_pointer_type_id() << ")).descriptor(), "
<< function;
if (!instruction.type->HasContextParameter()) {
// Add dummy context parameter to satisfy the CallBuiltinPointer signature.
out() << ", TNode<Object>()";
}
for (const std::string& argument : arguments) {
out() << ", " << argument;
}
out() << ")";
if (generated_type != "Object") out() << ")";
out() << ";\n";

View File

@ -103,6 +103,10 @@ Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
*signature.return_type, ".");
}
if (signature.return_type == TypeOracle::GetVoidType()) {
Error("Builtins cannot have return type void.");
}
return Declarations::CreateBuiltin(std::move(external_name),
std::move(readable_name), kind,
std::move(signature), body);

View File

@ -530,17 +530,8 @@ void ImplementationVisitor::Visit(Builtin* builtin) {
} else {
DCHECK(builtin->IsStub());
// Context
const bool context_is_implicit = signature.implicit_count > 0;
std::string parameter0 =
AddParameter(0, builtin, &parameters, &parameter_types,
&parameter_bindings, context_is_implicit);
source_out() << " TNode<Context> " << parameter0
<< " = UncheckedCast<Context>(Parameter("
<< "Descriptor::kContext));\n";
source_out() << " USE(" << parameter0 << ");\n";
for (size_t i = 1; i < signature.parameter_names.size(); ++i) {
bool has_context_parameter = signature.HasContextParameter();
for (size_t i = 0; i < signature.parameter_names.size(); ++i) {
const Type* type = signature.types()[i];
const bool mark_as_used = signature.implicit_count > i;
std::string var = AddParameter(i, builtin, &parameters, &parameter_types,
@ -548,8 +539,14 @@ void ImplementationVisitor::Visit(Builtin* builtin) {
source_out() << " " << type->GetGeneratedTypeName() << " " << var
<< " = "
<< "UncheckedCast<" << type->GetGeneratedTNodeTypeName()
<< ">(Parameter(Descriptor::ParameterIndex<" << (i - 1)
<< ">()));\n";
<< ">(Parameter(";
if (i == 0 && has_context_parameter) {
source_out() << "Descriptor::kContext";
} else {
source_out() << "Descriptor::ParameterIndex<"
<< (has_context_parameter ? i - 1 : i) << ">()";
}
source_out() << "));\n";
source_out() << " USE(" << var << ");\n";
}
}
@ -2980,13 +2977,15 @@ void ImplementationVisitor::GenerateBuiltinDefinitionsAndInterfaceDescriptors(
builtin_definitions << "TFC(" << builtin->ExternalName() << ", "
<< builtin->ExternalName();
std::string descriptor_name = builtin->ExternalName() + "Descriptor";
constexpr size_t kFirstNonContextParameter = 1;
bool has_context_parameter = builtin->signature().HasContextParameter();
size_t kFirstNonContextParameter = has_context_parameter ? 1 : 0;
size_t parameter_count =
builtin->parameter_names().size() - kFirstNonContextParameter;
interface_descriptors << "class " << descriptor_name
<< " : public TorqueInterfaceDescriptor<"
<< parameter_count << "> {\n";
interface_descriptors
<< "class " << descriptor_name
<< " : public TorqueInterfaceDescriptor<" << parameter_count << ", "
<< (has_context_parameter ? "true" : "false") << "> {\n";
interface_descriptors << " DECLARE_DESCRIPTOR_WITH_BASE("
<< descriptor_name
<< ", TorqueInterfaceDescriptor)\n";

View File

@ -705,6 +705,21 @@ bool Signature::HasSameTypesAs(const Signature& other,
return true;
}
namespace {
bool FirstTypeIsContext(const std::vector<const Type*> parameter_types) {
return !parameter_types.empty() &&
parameter_types[0] == TypeOracle::GetContextType();
}
} // namespace
bool Signature::HasContextParameter() const {
return FirstTypeIsContext(types());
}
bool BuiltinPointerType::HasContextParameter() const {
return FirstTypeIsContext(parameter_types());
}
bool IsAssignableFrom(const Type* to, const Type* from) {
if (to == from) return true;
if (from->IsSubtypeOf(to)) return true;

View File

@ -347,6 +347,8 @@ class V8_EXPORT_PRIVATE BuiltinPointerType final : public Type {
return {{"Smi", ""}};
}
bool HasContextParameter() const;
private:
friend class TypeOracle;
BuiltinPointerType(const Type* parent, TypeVector parameter_types,
@ -800,6 +802,7 @@ struct Signature {
return TypeVector(parameter_types.types.begin() + implicit_count,
parameter_types.types.end());
}
bool HasContextParameter() const;
};
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names);

View File

@ -113,8 +113,7 @@ TEST(TestBuiltinSpecialization) {
CodeAssemblerTester asm_tester(isolate, 0);
TestTorqueAssembler m(asm_tester.state());
{
TNode<Object> temp = m.SmiConstant(0);
m.TestBuiltinSpecialization(m.UncheckedCast<Context>(temp));
m.TestBuiltinSpecialization();
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
@ -170,8 +169,7 @@ TEST(TestFunctionPointerToGeneric) {
CodeAssemblerTester asm_tester(isolate, 0);
TestTorqueAssembler m(asm_tester.state());
{
TNode<Object> temp = m.SmiConstant(0);
m.TestFunctionPointerToGeneric(m.UncheckedCast<Context>(temp));
m.TestFunctionPointerToGeneric();
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);

View File

@ -97,20 +97,20 @@ namespace test {
}
}
builtin GenericBuiltinTest<T: type>(_c: Context, _param: T): JSAny {
builtin GenericBuiltinTest<T: type>(_param: T): JSAny {
return Null;
}
GenericBuiltinTest<JSAny>(_c: Context, param: JSAny): JSAny {
GenericBuiltinTest<JSAny>(param: JSAny): JSAny {
return param;
}
@export
macro TestBuiltinSpecialization(c: Context) {
check(GenericBuiltinTest<Smi>(c, 0) == Null);
check(GenericBuiltinTest<Smi>(c, 1) == Null);
check(GenericBuiltinTest<JSAny>(c, Undefined) == Undefined);
check(GenericBuiltinTest<JSAny>(c, Undefined) == Undefined);
macro TestBuiltinSpecialization() {
check(GenericBuiltinTest<Smi>(0) == Null);
check(GenericBuiltinTest<Smi>(1) == Null);
check(GenericBuiltinTest<JSAny>(Undefined) == Undefined);
check(GenericBuiltinTest<JSAny>(Undefined) == Undefined);
}
macro LabelTestHelper4(flag: constexpr bool): never
@ -185,19 +185,19 @@ namespace test {
}
}
builtin TestHelperPlus1(_context: Context, x: Smi): Smi {
builtin TestHelperPlus1(x: Smi): Smi {
return x + 1;
}
builtin TestHelperPlus2(_context: Context, x: Smi): Smi {
builtin TestHelperPlus2(x: Smi): Smi {
return x + 2;
}
@export
macro TestFunctionPointers(implicit context: Context)(): Boolean {
let fptr: builtin(Context, Smi) => Smi = TestHelperPlus1;
check(fptr(context, 42) == 43);
let fptr: builtin(Smi) => Smi = TestHelperPlus1;
check(fptr(42) == 43);
fptr = TestHelperPlus2;
check(fptr(context, 42) == 44);
check(fptr(42) == 44);
return True;
}
@ -215,14 +215,14 @@ namespace test {
}
@export
macro TestFunctionPointerToGeneric(c: Context) {
const fptr1: builtin(Context, Smi) => JSAny = GenericBuiltinTest<Smi>;
const fptr2: builtin(Context, JSAny) => JSAny = GenericBuiltinTest<JSAny>;
macro TestFunctionPointerToGeneric() {
const fptr1: builtin(Smi) => JSAny = GenericBuiltinTest<Smi>;
const fptr2: builtin(JSAny) => JSAny = GenericBuiltinTest<JSAny>;
check(fptr1(c, 0) == Null);
check(fptr1(c, 1) == Null);
check(fptr2(c, Undefined) == Undefined);
check(fptr2(c, Undefined) == Undefined);
check(fptr1(0) == Null);
check(fptr1(1) == Null);
check(fptr2(Undefined) == Undefined);
check(fptr2(Undefined) == Undefined);
}
type ObjectToObject = builtin(Context, JSAny) => JSAny;
@ -236,7 +236,7 @@ namespace test {
if (TaggedIsSmi(n)) {
const m: Smi = UnsafeCast<Smi>(n);
check(TestHelperPlus1(context, m) == 11);
check(TestHelperPlus1(m) == 11);
return True;
}
return False;