Commit 6955c553 authored by ishell's avatar ishell Committed by Commit bot

[turbofan] CodeAssembler is now able to generate calls of JavaScript objects.

... and a drive-by-fix of a comment generation in CodeAssembler.

Review-Url: https://codereview.chromium.org/2076953002
Cr-Commit-Position: refs/heads/master@{#37070}
parent b98e3949
......@@ -174,9 +174,10 @@ void CodeAssembler::Comment(const char* format, ...) {
// Copy the string before recording it in the assembler to avoid
// issues when the stack allocated buffer goes out of scope.
size_t length = builder.position() + 3;
char* copy = reinterpret_cast<char*>(malloc(static_cast<int>(length)));
MemCopy(copy + 2, builder.Finalize(), length);
const int prefix_len = 2;
int length = builder.position() + 1;
char* copy = reinterpret_cast<char*>(malloc(length + prefix_len));
MemCopy(copy + prefix_len, builder.Finalize(), length);
copy[0] = ';';
copy[1] = ' ';
raw_assembler_->Comment(copy);
......@@ -577,6 +578,66 @@ Node* CodeAssembler::TailCallBytecodeDispatch(
return raw_assembler_->TailCallN(descriptor, code_target_address, args);
}
Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
Node* function, Node* receiver,
size_t result_size) {
const int argc = 0;
CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
isolate(), zone(), callable.descriptor(), argc + 1,
CallDescriptor::kNoFlags, Operator::kNoProperties,
MachineType::AnyTagged(), result_size);
Node* target = HeapConstant(callable.code());
Node** args = zone()->NewArray<Node*>(argc + 4);
args[0] = function;
args[1] = Int32Constant(argc);
args[2] = receiver;
args[3] = context;
return CallN(call_descriptor, target, args);
}
Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
Node* function, Node* receiver, Node* arg1,
size_t result_size) {
const int argc = 1;
CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
isolate(), zone(), callable.descriptor(), argc + 1,
CallDescriptor::kNoFlags, Operator::kNoProperties,
MachineType::AnyTagged(), result_size);
Node* target = HeapConstant(callable.code());
Node** args = zone()->NewArray<Node*>(argc + 4);
args[0] = function;
args[1] = Int32Constant(argc);
args[2] = receiver;
args[3] = arg1;
args[4] = context;
return CallN(call_descriptor, target, args);
}
Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
Node* function, Node* receiver, Node* arg1,
Node* arg2, size_t result_size) {
const int argc = 2;
CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
isolate(), zone(), callable.descriptor(), argc + 1,
CallDescriptor::kNoFlags, Operator::kNoProperties,
MachineType::AnyTagged(), result_size);
Node* target = HeapConstant(callable.code());
Node** args = zone()->NewArray<Node*>(argc + 4);
args[0] = function;
args[1] = Int32Constant(argc);
args[2] = receiver;
args[3] = arg1;
args[4] = arg2;
args[5] = context;
return CallN(call_descriptor, target, args);
}
void CodeAssembler::Goto(CodeAssembler::Label* label) {
label->MergeVariables();
raw_assembler_->Goto(label->label_);
......
......@@ -340,6 +340,13 @@ class CodeAssembler {
Node* TailCallBytecodeDispatch(const CallInterfaceDescriptor& descriptor,
Node* code_target_address, Node** args);
Node* CallJS(Callable const& callable, Node* context, Node* function,
Node* receiver, size_t result_size = 1);
Node* CallJS(Callable const& callable, Node* context, Node* function,
Node* receiver, Node* arg1, size_t result_size = 1);
Node* CallJS(Callable const& callable, Node* context, Node* function,
Node* receiver, Node* arg1, Node* arg2, size_t result_size = 1);
// Branching helpers.
void BranchIf(Node* condition, Label* if_true, Label* if_false);
......
......@@ -61,6 +61,11 @@ class FunctionTester : public InitializedHandleScope {
return Execution::Call(isolate, function, undefined(), 0, nullptr);
}
MaybeHandle<Object> Call(Handle<Object> a) {
Handle<Object> args[] = {a};
return Execution::Call(isolate, function, undefined(), 1, args);
}
MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) {
Handle<Object> args[] = {a, b};
return Execution::Call(isolate, function, undefined(), 2, args);
......
......@@ -124,6 +124,91 @@ TEST(SimpleTailCallRuntime2Arg) {
CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
}
namespace {
Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) {
const char* source =
"(function() {\n"
" var sum = 0 + this;\n"
" for (var i = 0; i < arguments.length; i++) {\n"
" sum += arguments[i];\n"
" }\n"
" return sum;\n"
"})";
return ft.NewFunction(source);
}
} // namespace
TEST(SimpleCallJSFunction0Arg) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1;
CodeAssemblerTester m(isolate, kNumParams);
{
Node* function = m.Parameter(0);
Node* context = m.Parameter(kNumParams + 2);
Node* receiver = SmiTag(m, m.Int32Constant(42));
Callable callable = CodeFactory::Call(isolate);
Node* result = m.CallJS(callable, context, function, receiver);
m.Return(result);
}
Handle<Code> code = m.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
MaybeHandle<Object> result = ft.Call(sum);
CHECK_EQ(Smi::FromInt(42), *result.ToHandleChecked());
}
TEST(SimpleCallJSFunction1Arg) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2;
CodeAssemblerTester m(isolate, kNumParams);
{
Node* function = m.Parameter(0);
Node* context = m.Parameter(1);
Node* receiver = SmiTag(m, m.Int32Constant(42));
Node* a = SmiTag(m, m.Int32Constant(13));
Callable callable = CodeFactory::Call(isolate);
Node* result = m.CallJS(callable, context, function, receiver, a);
m.Return(result);
}
Handle<Code> code = m.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
MaybeHandle<Object> result = ft.Call(sum);
CHECK_EQ(Smi::FromInt(55), *result.ToHandleChecked());
}
TEST(SimpleCallJSFunction2Arg) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2;
CodeAssemblerTester m(isolate, kNumParams);
{
Node* function = m.Parameter(0);
Node* context = m.Parameter(1);
Node* receiver = SmiTag(m, m.Int32Constant(42));
Node* a = SmiTag(m, m.Int32Constant(13));
Node* b = SmiTag(m, m.Int32Constant(153));
Callable callable = CodeFactory::Call(isolate);
Node* result = m.CallJS(callable, context, function, receiver, a, b);
m.Return(result);
}
Handle<Code> code = m.GenerateCode();
FunctionTester ft(code, kNumParams);
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
MaybeHandle<Object> result = ft.Call(sum);
CHECK_EQ(Smi::FromInt(208), *result.ToHandleChecked());
}
TEST(VariableMerge1) {
Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate);
......
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