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}
This commit is contained in:
vogelheim 2016-02-02 02:59:19 -08:00 committed by Commit bot
parent 3f4163cd24
commit d472cf4484
5 changed files with 121 additions and 8 deletions

View File

@ -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;

View File

@ -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

View File

@ -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_);

View File

@ -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();

View File

@ -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);
}