Commit 93df7ff0 authored by Mike Stanton's avatar Mike Stanton Committed by Commit Bot

[Torque] Support JavaScript builtins with fixed args

To implement builtin continuations called from the deoptimizer,
we need to better support writing builtins declared with javascript
binding in Torque. This CL adds fixed number of argument support.
So you can declare in Torque, something like:

builtin javascript Foo(context: Context, receiver: Object, bar: Object):
  Object {
  ...
}

Formerly, this would give you an error because we only supported
javascript bindings with a varargs array.

Bug: v8:7672
Change-Id: I5b5b25bdbbd5e054049c39dd2f1a4c606472dcd5
Reviewed-on: https://chromium-review.googlesource.com/1018941
Commit-Queue: Michael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52704}
parent d9015ef8
......@@ -218,15 +218,19 @@ class MacroList : public Declarable {
class Builtin : public Callable {
public:
Builtin(const std::string& name, bool java_script, Scope* scope,
enum Kind { kStub = 0, kFixedArgsJavaScript, kVarArgsJavaScript };
Builtin(const std::string& name, Kind kind, Scope* scope,
const Signature& signature)
: Callable(Declarable::kBuiltin, name, scope, signature),
java_script_(java_script) {}
: Callable(Declarable::kBuiltin, name, scope, signature), kind_(kind) {}
DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin);
bool IsJavaScript() const { return java_script_; }
Kind kind() const { return kind_; }
bool IsStub() const { return kind_ == kStub; }
bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; }
bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
private:
bool java_script_;
Kind kind_;
};
class Runtime : public Callable {
......
......@@ -66,23 +66,16 @@ void DeclarationVisitor::Visit(BuiltinDeclaration* decl) {
std::cout << decl->name << " with signature " << signature << std::endl;
}
bool java_script = decl->javascript_linkage;
bool varargs = decl->parameters.has_varargs;
if (java_script != varargs) {
if (java_script) {
std::stringstream stream;
stream << "JavaScript builtin " << decl->name
<< " must have rest parameters at " << PositionAsString(decl->pos);
ReportError(stream.str());
} else {
std::stringstream stream;
stream << "builtin " << decl->name
<< " with rest parameters must be a JavaScript builtin at "
<< PositionAsString(decl->pos);
ReportError(stream.str());
}
const bool javascript = decl->javascript_linkage;
const bool varargs = decl->parameters.has_varargs;
if (varargs && !javascript) {
std::stringstream stream;
stream << "builtin " << decl->name
<< " with rest parameters must be a JavaScript builtin at "
<< PositionAsString(decl->pos);
ReportError(stream.str());
}
if (java_script && varargs) {
if (javascript) {
if (signature.types().size() < 2 ||
!signature.types()[1].Is(OBJECT_TYPE_STRING)) {
std::stringstream stream;
......@@ -99,8 +92,11 @@ void DeclarationVisitor::Visit(BuiltinDeclaration* decl) {
"arguments");
}
Builtin::Kind kind = !javascript ? Builtin::kStub
: varargs ? Builtin::kVarArgsJavaScript
: Builtin::kFixedArgsJavaScript;
Builtin* builtin = enclosing_scope->DeclareBuiltin(
decl->pos, decl->name, java_script, new_scope, signature);
decl->pos, decl->name, kind, new_scope, signature);
defined_builtins_.push_back(builtin);
DeclareParameterList(decl->pos, signature);
CurrentCallActivator activator(global_context_, builtin);
......
......@@ -91,22 +91,16 @@ class DeclarationVisitor : public FileVisitor {
<< PositionAsString(decl->pos);
ReportError(stream.str());
}
if (decl->javascript_linkage != decl->parameters.has_varargs) {
if (decl->javascript_linkage) {
std::stringstream stream;
stream << "JavaScript builtin " << decl->name
<< " must have rest parameters at "
<< PositionAsString(decl->pos);
ReportError(stream.str());
} else {
std::stringstream stream;
stream << "builtin " << decl->name
<< " with rest parameters must be a JavaScript builtin at "
<< PositionAsString(decl->pos);
ReportError(stream.str());
}
const bool javascript = decl->javascript_linkage;
const bool varargs = decl->parameters.has_varargs;
if (varargs && !javascript) {
std::stringstream stream;
stream << "builtin " << decl->name
<< " with rest parameters must be a JavaScript builtin at "
<< PositionAsString(decl->pos);
ReportError(stream.str());
}
if (decl->javascript_linkage && decl->parameters.has_varargs) {
if (javascript) {
if (signature.types().size() < 2 ||
!signature.types()[1].Is(OBJECT_TYPE_STRING)) {
std::stringstream stream;
......@@ -116,8 +110,10 @@ class DeclarationVisitor : public FileVisitor {
ReportError(stream.str());
}
}
TopScope()->DeclareBuiltin(decl->pos, decl->name, decl->javascript_linkage,
nullptr, signature);
Builtin::Kind kind = !javascript ? Builtin::kStub
: varargs ? Builtin::kVarArgsJavaScript
: Builtin::kFixedArgsJavaScript;
TopScope()->DeclareBuiltin(decl->pos, decl->name, kind, nullptr, signature);
}
void Visit(ExternalRuntimeDeclaration* decl) {
......@@ -310,19 +306,34 @@ class DeclarationVisitor : public FileVisitor {
"#define BUILTIN_LIST_FROM_DSL(CPP, API, TFJ, TFC, TFS, TFH, ASM) "
"\\\n";
for (auto builtin : defined_builtins_) {
bool first = true;
if (builtin->IsJavaScript()) {
new_contents_stream
<< "TFJ(" << builtin->name()
<< ", SharedFunctionInfo::kDontAdaptArgumentsSentinel";
} else {
int firstParameterIndex = 1;
bool declareParameters = true;
if (builtin->IsStub()) {
new_contents_stream << "TFS(" << builtin->name();
} else {
new_contents_stream << "TFJ(" << builtin->name();
if (builtin->IsVarArgsJavaScript()) {
new_contents_stream
<< ", SharedFunctionInfo::kDontAdaptArgumentsSentinel";
declareParameters = false;
} else {
assert(builtin->IsFixedArgsJavaScript());
// FixedArg javascript builtins need to offer the parameter
// count.
assert(builtin->parameter_names().size() >= 2);
new_contents_stream << ", "
<< (builtin->parameter_names().size() - 2);
// And the receiver is implicitly declared.
firstParameterIndex = 2;
}
}
if (declareParameters) {
int index = 0;
for (auto parameter : builtin->parameter_names()) {
if (first) {
first = false;
} else {
if (index >= firstParameterIndex) {
new_contents_stream << ", k" << CamelifyString(parameter);
}
index++;
}
}
new_contents_stream << ") \\\n";
......
......@@ -212,38 +212,37 @@ void ImplementationVisitor::Visit(BuiltinDeclaration* decl) {
GenerateIndent();
source_out() << "TNode<Context> " << val->GetValueForDeclaration()
<< " = UncheckedCast<Context>(Parameter("
<< (builtin->IsJavaScript() ? "Builtin" : "")
<< (builtin->IsVarArgsJavaScript() ? "Builtin" : "")
<< "Descriptor::kContext));" << std::endl;
GenerateIndent();
source_out() << "USE(" << val->GetValueForDeclaration() << ");" << std::endl;
size_t first = 1;
if (builtin->IsJavaScript()) {
if (decl->parameters.has_varargs) {
Constant* arguments = Constant::cast(
LookupValue(decl->pos, decl->parameters.arguments_variable));
std::string arguments_name = arguments->GetValueForDeclaration();
GenerateIndent();
source_out()
<< "Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);"
<< std::endl;
GenerateIndent();
source_out() << "CodeStubArguments arguments_impl(this, "
"ChangeInt32ToIntPtr(argc));"
<< std::endl;
const Value* receiver = LookupValue(decl->pos, decl->parameters.names[1]);
GenerateIndent();
source_out() << "TNode<Object> " << receiver->GetValueForDeclaration()
<< " = arguments_impl.GetReceiver();" << std::endl;
GenerateIndent();
source_out() << "auto arguments = &arguments_impl;" << std::endl;
GenerateIndent();
source_out() << "USE(arguments);" << std::endl;
GenerateIndent();
source_out() << "USE(" << receiver->GetValueForDeclaration() << ");"
<< std::endl;
first = 2;
}
if (builtin->IsVarArgsJavaScript()) {
assert(decl->parameters.has_varargs);
Constant* arguments = Constant::cast(
LookupValue(decl->pos, decl->parameters.arguments_variable));
std::string arguments_name = arguments->GetValueForDeclaration();
GenerateIndent();
source_out()
<< "Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);"
<< std::endl;
GenerateIndent();
source_out() << "CodeStubArguments arguments_impl(this, "
"ChangeInt32ToIntPtr(argc));"
<< std::endl;
const Value* receiver = LookupValue(decl->pos, decl->parameters.names[1]);
GenerateIndent();
source_out() << "TNode<Object> " << receiver->GetValueForDeclaration()
<< " = arguments_impl.GetReceiver();" << std::endl;
GenerateIndent();
source_out() << "auto arguments = &arguments_impl;" << std::endl;
GenerateIndent();
source_out() << "USE(arguments);" << std::endl;
GenerateIndent();
source_out() << "USE(" << receiver->GetValueForDeclaration() << ");"
<< std::endl;
first = 2;
}
GenerateParameterList(decl->pos, decl->parameters.names, first);
......@@ -582,7 +581,7 @@ Type ImplementationVisitor::Visit(ReturnStatement* stmt) {
GenerateAssignToVariable(stmt->pos, var, return_result);
GenerateLabelGoto(end);
} else if (current_callable->IsBuiltin()) {
if (Builtin::cast(current_callable)->IsJavaScript()) {
if (Builtin::cast(current_callable)->IsVarArgsJavaScript()) {
GenerateIndent();
source_out() << "arguments->PopAndReturn(" << return_result.variable()
<< ");" << std::endl;
......
......@@ -52,10 +52,10 @@ Macro* Scope::DeclareMacro(SourcePosition pos, const std::string& name,
}
Builtin* Scope::DeclareBuiltin(SourcePosition pos, const std::string& name,
bool java_script, Scope* scope,
Builtin::Kind kind, Scope* scope,
const Signature& signature) {
CheckAlreadyDeclared(pos, name, "builtin");
Builtin* result = new Builtin(name, java_script, scope, signature);
Builtin* result = new Builtin(name, kind, scope, signature);
lookup_[name] = result;
if (global_context_.verbose()) {
std::cout << "declared " << *result << "\n";
......
......@@ -33,7 +33,7 @@ class Scope {
const Signature& signature);
Builtin* DeclareBuiltin(SourcePosition pos, const std::string& name,
bool java_script, Scope* scope,
Builtin::Kind kind, Scope* scope,
const Signature& signature);
Runtime* DeclareRuntime(SourcePosition pos, const std::string& name,
......
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