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:
parent
3f4163cd24
commit
d472cf4484
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user