[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:
parent
2ce3a8e973
commit
b5ab5c7b75
@ -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)(
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>());
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -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, ¶meters, ¶meter_types,
|
||||
¶meter_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, ¶meters, ¶meter_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";
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user