Commit d472cf44 authored by vogelheim's avatar vogelheim Committed by Commit bot

Add native callbacks to FastAccessorAssembler.

(Trying to finish FastAccessorAssembler this week. This should make it easier to pick up the Blink side of this work later on.)

BUG=chromium:508898
SOUNDTRACK=http://youtu.be/i1EG-MKy4so
LOG=Y

Review URL: https://codereview.chromium.org/1620293002

Cr-Commit-Position: refs/heads/master@{#33671}
parent 3f4163cd
......@@ -39,6 +39,7 @@ class V8_EXPORT FastAccessorBuilder {
LabelId MakeLabel();
void SetLabel(LabelId label_id);
void CheckNotZeroOrJump(ValueId value_id, LabelId label_id);
ValueId Call(v8::FunctionCallback callback, ValueId value_id);
private:
FastAccessorBuilder() = delete;
......
......@@ -122,5 +122,11 @@ void FastAccessorBuilder::CheckNotZeroOrJump(ValueId value_id,
FromApi(this)->CheckNotZeroOrJump(value_id, label_id);
}
FastAccessorBuilder::ValueId FastAccessorBuilder::Call(
v8::FunctionCallback callback, ValueId value_id) {
return FromApi(this)->Call(callback, value_id);
}
} // namespace experimental
} // namespace v8
......@@ -5,6 +5,7 @@
#include "src/compiler/fast-accessor-assembler.h"
#include "src/base/logging.h"
#include "src/code-stubs.h" // For CallApiFunctionStub.
#include "src/compiler/graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline.h"
......@@ -167,6 +168,48 @@ void FastAccessorAssembler::CheckNotZeroOrJump(ValueId value_id,
}
FastAccessorAssembler::ValueId FastAccessorAssembler::Call(
FunctionCallback callback_function, ValueId arg) {
CHECK_EQ(kBuilding, state_);
// Create API function stub.
CallApiFunctionStub stub(assembler_->isolate(), true);
// Wrap the FunctionCallback in an ExternalReference.
ApiFunction callback_api_function(FUNCTION_ADDR(callback_function));
ExternalReference callback(&callback_api_function,
ExternalReference::DIRECT_API_CALL,
assembler_->isolate());
// The stub has 5 parameters, and kJSParam (here: 1) parameters to pass
// through to the callback.
// See: ApiFunctionDescriptor::BuildCallInterfaceDescriptorFunctionType
static const int kStackParam = 1;
Node* args[] = {
// Stub/register parameters:
assembler_->Parameter(0), /* receiver (use accessor's) */
assembler_->UndefinedConstant(), /* call_data (undefined) */
assembler_->NullConstant(), /* holder (null) */
assembler_->ExternalConstant(callback), /* API callback function */
assembler_->IntPtrConstant(kStackParam), /* # JS arguments */
// kStackParam stack parameter(s):
FromId(arg),
// Context parameter. (See Linkage::GetStubCallDescriptor.)
assembler_->UndefinedConstant()};
CHECK_EQ(5 + kStackParam + 1, arraysize(args));
Node* call = assembler_->CallN(
Linkage::GetStubCallDescriptor(
assembler_->isolate(), zone(), stub.GetCallInterfaceDescriptor(),
kStackParam + stub.GetStackParameterCount(),
CallDescriptor::kNoFlags),
assembler_->HeapConstant(stub.GetCode()), args);
return FromRaw(call);
}
MaybeHandle<Code> FastAccessorAssembler::Build() {
CHECK_EQ(kBuilding, state_);
......
......@@ -48,6 +48,7 @@ class FastAccessorAssembler {
public:
typedef v8::experimental::FastAccessorBuilder::ValueId ValueId;
typedef v8::experimental::FastAccessorBuilder::LabelId LabelId;
typedef v8::FunctionCallback FunctionCallback;
explicit FastAccessorAssembler(Isolate* isolate);
~FastAccessorAssembler();
......@@ -63,15 +64,13 @@ class FastAccessorAssembler {
void ReturnValue(ValueId value_id);
void CheckFlagSetOrReturnNull(ValueId value_id, int mask);
void CheckNotZeroOrReturnNull(ValueId value_id);
// TODO(vogelheim): Implement a C++ callback.
// void CheckNotNullOrCallback(ValueId value_id, ..c++-callback type...,
// ValueId arg1, ValueId arg2, ...);
LabelId MakeLabel();
void SetLabel(LabelId label_id);
void CheckNotZeroOrJump(ValueId value_id, LabelId label_id);
// C++ callback.
ValueId Call(FunctionCallback callback, ValueId arg);
// Assemble the code.
MaybeHandle<Code> Build();
......
......@@ -51,9 +51,9 @@ namespace {
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
"*/ " // 16 lines * 64 'X' =~ 1024 character comment.
#define FN_WARMUP(name, src) \
"function " name "() { " src INLINE_SPOILER \
" }; for(i = 0; i < 2; i++) { " name "() } "
#define FN(name, src) "function " name "() { " src INLINE_SPOILER " }"
#define WARMUP(name, count) "for(i = 0; i < " count "; i++) { " name "() } "
#define FN_WARMUP(name, src) FN(name, src) "; " WARMUP(name, "2")
static void NativePropertyAccessor(
const v8::FunctionCallbackInfo<v8::Value>& info) {
......@@ -286,3 +286,67 @@ TEST(FastAccessorLoad) {
CompileRun(FN_WARMUP("loadval", "return obj.loadval"));
ExpectString("loadval()", "Hello");
}
void ApiCallbackInt(const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(12345);
}
const char* kApiCallbackStringValue =
"Hello World! Bizarro C++ world, actually.";
void ApiCallbackString(const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(v8_str(kApiCallbackStringValue));
}
void ApiCallbackParam(const v8::FunctionCallbackInfo<v8::Value>& info) {
CHECK_EQ(1, info.Length());
CHECK(info[0]->IsNumber());
info.GetReturnValue().Set(info[0]);
}
// "Fast" accessor, callback to embedder
TEST(FastAccessorCallback) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
v8::Local<v8::ObjectTemplate> foo = v8::ObjectTemplate::New(isolate);
{
auto builder = v8::experimental::FastAccessorBuilder::New(isolate);
builder->ReturnValue(
builder->Call(&ApiCallbackInt, builder->IntegerConstant(999)));
foo->SetAccessorProperty(v8_str("int"),
v8::FunctionTemplate::NewWithFastHandler(
isolate, NativePropertyAccessor, builder));
builder = v8::experimental::FastAccessorBuilder::New(isolate);
builder->ReturnValue(
builder->Call(&ApiCallbackString, builder->IntegerConstant(0)));
foo->SetAccessorProperty(v8_str("str"),
v8::FunctionTemplate::NewWithFastHandler(
isolate, NativePropertyAccessor, builder));
builder = v8::experimental::FastAccessorBuilder::New(isolate);
builder->ReturnValue(
builder->Call(&ApiCallbackParam, builder->IntegerConstant(1000)));
foo->SetAccessorProperty(v8_str("param"),
v8::FunctionTemplate::NewWithFastHandler(
isolate, NativePropertyAccessor, builder));
}
// Create an instance.
v8::Local<v8::Object> obj = foo->NewInstance(env.local()).ToLocalChecked();
CHECK(env->Global()->Set(env.local(), v8_str("obj"), obj).FromJust());
// Callbacks:
CompileRun(FN_WARMUP("callbackint", "return obj.int"));
ExpectInt32("callbackint()", 12345);
CompileRun(FN_WARMUP("callbackstr", "return obj.str"));
ExpectString("callbackstr()", kApiCallbackStringValue);
CompileRun(FN_WARMUP("callbackparam", "return obj.param"));
ExpectInt32("callbackparam()", 1000);
}
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