Commit 3f027300 authored by verwaest's avatar verwaest Committed by Commit bot

Simplify the interface of PropertyCallbackArguments

Use internal handles as API, and move boilerplate code into the call wrappers.
BUG=

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

Cr-Commit-Position: refs/heads/master@{#34684}
parent d30af81e
...@@ -4,82 +4,28 @@ ...@@ -4,82 +4,28 @@
#include "src/api-arguments.h" #include "src/api-arguments.h"
#include "src/api.h"
#include "src/vm-state-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
template <typename T> Handle<Object> FunctionCallbackArguments::Call(FunctionCallback f) {
template <typename V>
v8::Local<V> CustomArguments<T>::GetReturnValue(Isolate* isolate) {
// Check the ReturnValue.
Object** handle = &this->begin()[kReturnValueOffset];
// Nothing was set, return empty handle as per previous behaviour.
if ((*handle)->IsTheHole()) return v8::Local<V>();
return Utils::Convert<Object, V>(Handle<Object>(handle));
}
v8::Local<v8::Value> FunctionCallbackArguments::Call(FunctionCallback f) {
Isolate* isolate = this->isolate(); Isolate* isolate = this->isolate();
VMState<EXTERNAL> state(isolate); VMState<EXTERNAL> state(isolate);
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
FunctionCallbackInfo<v8::Value> info(begin(), argv_, argc_, FunctionCallbackInfo<v8::Value> info(begin(), argv_, argc_,
is_construct_call_); is_construct_call_);
f(info); f(info);
return GetReturnValue<v8::Value>(isolate); return GetReturnValue<Object>(isolate);
} }
#define WRITE_CALL_0(Function, ReturnValue) \ Handle<JSObject> PropertyCallbackArguments::Call(
v8::Local<ReturnValue> PropertyCallbackArguments::Call(Function f) { \ IndexedPropertyEnumeratorCallback f) {
Isolate* isolate = this->isolate(); \ Isolate* isolate = this->isolate();
VMState<EXTERNAL> state(isolate); \ VMState<EXTERNAL> state(isolate);
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \ ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
PropertyCallbackInfo<ReturnValue> info(begin()); \ PropertyCallbackInfo<v8::Array> info(begin());
f(info); \ f(info);
return GetReturnValue<ReturnValue>(isolate); \ return GetReturnValue<JSObject>(isolate);
} }
#define WRITE_CALL_1(Function, ReturnValue, Arg1) \
v8::Local<ReturnValue> PropertyCallbackArguments::Call(Function f, \
Arg1 arg1) { \
Isolate* isolate = this->isolate(); \
VMState<EXTERNAL> state(isolate); \
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
PropertyCallbackInfo<ReturnValue> info(begin()); \
f(arg1, info); \
return GetReturnValue<ReturnValue>(isolate); \
}
#define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \
v8::Local<ReturnValue> PropertyCallbackArguments::Call( \
Function f, Arg1 arg1, Arg2 arg2) { \
Isolate* isolate = this->isolate(); \
VMState<EXTERNAL> state(isolate); \
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
PropertyCallbackInfo<ReturnValue> info(begin()); \
f(arg1, arg2, info); \
return GetReturnValue<ReturnValue>(isolate); \
}
#define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \
void PropertyCallbackArguments::Call(Function f, Arg1 arg1, Arg2 arg2) { \
Isolate* isolate = this->isolate(); \
VMState<EXTERNAL> state(isolate); \
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
PropertyCallbackInfo<ReturnValue> info(begin()); \
f(arg1, arg2, info); \
}
FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0)
FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1)
FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2)
FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID)
#undef WRITE_CALL_0
#undef WRITE_CALL_1
#undef WRITE_CALL_2
#undef WRITE_CALL_2_VOID
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -5,37 +5,14 @@ ...@@ -5,37 +5,14 @@
#ifndef V8_API_ARGUMENTS_H_ #ifndef V8_API_ARGUMENTS_H_
#define V8_API_ARGUMENTS_H_ #define V8_API_ARGUMENTS_H_
#include "src/api.h"
#include "src/isolate.h" #include "src/isolate.h"
#include "src/tracing/trace-event.h" #include "src/tracing/trace-event.h"
#include "src/vm-state-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
// For each type of callback, we have a list of arguments
// They are used to generate the Call() functions below
// These aren't included in the list as they have duplicate signatures
// F(GenericNamedPropertyEnumeratorCallback, ...)
// F(GenericNamedPropertyGetterCallback, ...)
#define FOR_EACH_CALLBACK_TABLE_MAPPING_0(F) \
F(IndexedPropertyEnumeratorCallback, v8::Array)
#define FOR_EACH_CALLBACK_TABLE_MAPPING_1(F) \
F(AccessorNameGetterCallback, v8::Value, v8::Local<v8::Name>) \
F(GenericNamedPropertyQueryCallback, v8::Integer, v8::Local<v8::Name>) \
F(GenericNamedPropertyDeleterCallback, v8::Boolean, v8::Local<v8::Name>) \
F(IndexedPropertyGetterCallback, v8::Value, uint32_t) \
F(IndexedPropertyQueryCallback, v8::Integer, uint32_t) \
F(IndexedPropertyDeleterCallback, v8::Boolean, uint32_t)
#define FOR_EACH_CALLBACK_TABLE_MAPPING_2(F) \
F(GenericNamedPropertySetterCallback, v8::Value, v8::Local<v8::Name>, \
v8::Local<v8::Value>) \
F(IndexedPropertySetterCallback, v8::Value, uint32_t, v8::Local<v8::Value>)
#define FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(F) \
F(AccessorNameSetterCallback, void, v8::Local<v8::Name>, v8::Local<v8::Value>)
// Custom arguments replicate a small segment of stack that can be // Custom arguments replicate a small segment of stack that can be
// accessed through an Arguments object the same way the actual stack // accessed through an Arguments object the same way the actual stack
// can. // can.
...@@ -68,13 +45,25 @@ class CustomArguments : public CustomArgumentsBase<T::kArgsLength> { ...@@ -68,13 +45,25 @@ class CustomArguments : public CustomArgumentsBase<T::kArgsLength> {
explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {} explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {}
template <typename V> template <typename V>
v8::Local<V> GetReturnValue(Isolate* isolate); Handle<V> GetReturnValue(Isolate* isolate);
inline Isolate* isolate() { inline Isolate* isolate() {
return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]); return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]);
} }
}; };
template <typename T>
template <typename V>
Handle<V> CustomArguments<T>::GetReturnValue(Isolate* isolate) {
// Check the ReturnValue.
Object** handle = &this->begin()[kReturnValueOffset];
// Nothing was set, return empty handle as per previous behaviour.
if ((*handle)->IsTheHole()) return Handle<V>();
Handle<V> result = Handle<V>::cast(Handle<Object>(handle));
result->VerifyApiCallResultType();
return result;
}
class PropertyCallbackArguments class PropertyCallbackArguments
: public CustomArguments<PropertyCallbackInfo<Value> > { : public CustomArguments<PropertyCallbackInfo<Value> > {
public: public:
...@@ -117,27 +106,91 @@ class PropertyCallbackArguments ...@@ -117,27 +106,91 @@ class PropertyCallbackArguments
* and used if it's been set to anything inside the callback. * and used if it's been set to anything inside the callback.
* New style callbacks always use the return value. * New style callbacks always use the return value.
*/ */
#define WRITE_CALL_0(Function, ReturnValue) \ Handle<JSObject> Call(IndexedPropertyEnumeratorCallback f);
v8::Local<ReturnValue> Call(Function f);
#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(F) \
F(AccessorNameGetterCallback, "get", v8::Value, Object) \
F(GenericNamedPropertyQueryCallback, "has", v8::Integer, Object) \
F(GenericNamedPropertyDeleterCallback, "delete", v8::Boolean, Object)
#define WRITE_CALL_1_NAME(Function, type, ApiReturn, InternalReturn) \
Handle<InternalReturn> Call(Function f, Handle<Name> name) { \
Isolate* isolate = this->isolate(); \
VMState<EXTERNAL> state(isolate); \
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
PropertyCallbackInfo<ApiReturn> info(begin()); \
LOG(isolate, \
ApiNamedPropertyAccess("interceptor-named-" type, holder(), *name)); \
f(v8::Utils::ToLocal(name), info); \
return GetReturnValue<InternalReturn>(isolate); \
}
#define WRITE_CALL_1(Function, ReturnValue, Arg1) \ FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(WRITE_CALL_1_NAME)
v8::Local<ReturnValue> Call(Function f, Arg1 arg1);
#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME
#undef WRITE_CALL_1_NAME
#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(F) \
F(IndexedPropertyGetterCallback, "get", v8::Value, Object) \
F(IndexedPropertyQueryCallback, "has", v8::Integer, Object) \
F(IndexedPropertyDeleterCallback, "delete", v8::Boolean, Object)
#define WRITE_CALL_1_INDEX(Function, type, ApiReturn, InternalReturn) \
Handle<InternalReturn> Call(Function f, uint32_t index) { \
Isolate* isolate = this->isolate(); \
VMState<EXTERNAL> state(isolate); \
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
PropertyCallbackInfo<ApiReturn> info(begin()); \
LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-" type, \
holder(), index)); \
f(index, info); \
return GetReturnValue<InternalReturn>(isolate); \
}
#define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2) \ FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(WRITE_CALL_1_INDEX)
v8::Local<ReturnValue> Call(Function f, Arg1 arg1, Arg2 arg2);
#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX
#undef WRITE_CALL_1_INDEX
Handle<Object> Call(GenericNamedPropertySetterCallback f, Handle<Name> name,
Handle<Object> value) {
Isolate* isolate = this->isolate();
VMState<EXTERNAL> state(isolate);
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
PropertyCallbackInfo<v8::Value> info(begin());
LOG(isolate,
ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
return GetReturnValue<Object>(isolate);
}
#define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2) \ Handle<Object> Call(IndexedPropertySetterCallback f, uint32_t index,
void Call(Function f, Arg1 arg1, Arg2 arg2); Handle<Object> value) {
Isolate* isolate = this->isolate();
VMState<EXTERNAL> state(isolate);
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
PropertyCallbackInfo<v8::Value> info(begin());
LOG(isolate,
ApiIndexedPropertyAccess("interceptor-indexed-set", holder(), index));
f(index, v8::Utils::ToLocal(value), info);
return GetReturnValue<Object>(isolate);
}
FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0) void Call(AccessorNameSetterCallback f, Handle<Name> name,
FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1) Handle<Object> value) {
FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2) Isolate* isolate = this->isolate();
FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID) VMState<EXTERNAL> state(isolate);
ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
PropertyCallbackInfo<void> info(begin());
LOG(isolate,
ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
}
#undef WRITE_CALL_0 private:
#undef WRITE_CALL_1 inline JSObject* holder() {
#undef WRITE_CALL_2 return JSObject::cast(this->begin()[T::kHolderIndex]);
#undef WRITE_CALL_2_VOID }
}; };
class FunctionCallbackArguments class FunctionCallbackArguments
...@@ -187,7 +240,7 @@ class FunctionCallbackArguments ...@@ -187,7 +240,7 @@ class FunctionCallbackArguments
* and used if it's been set to anything inside the callback. * and used if it's been set to anything inside the callback.
* New style callbacks always use the return value. * New style callbacks always use the return value.
*/ */
v8::Local<v8::Value> Call(FunctionCallback f); Handle<Object> Call(FunctionCallback f);
private: private:
internal::Object** argv_; internal::Object** argv_;
......
...@@ -3970,14 +3970,8 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper( ...@@ -3970,14 +3970,8 @@ MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
args.length() - 1, args.length() - 1,
is_construct); is_construct);
v8::Local<v8::Value> value = custom.Call(callback); Handle<Object> result = custom.Call(callback);
Handle<Object> result; if (result.is_null()) result = isolate->factory()->undefined_value();
if (value.IsEmpty()) {
result = isolate->factory()->undefined_value();
} else {
result = v8::Utils::OpenHandle(*value);
result->VerifyApiCallResultType();
}
RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
if (!is_construct || result->IsJSObject()) { if (!is_construct || result->IsJSObject()) {
...@@ -4144,8 +4138,6 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function, ...@@ -4144,8 +4138,6 @@ MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<HeapObject> function,
MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor( MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
Isolate* isolate, bool is_construct_call, Isolate* isolate, bool is_construct_call,
BuiltinArguments<BuiltinExtraArguments::kNone> args) { BuiltinArguments<BuiltinExtraArguments::kNone> args) {
Heap* heap = isolate->heap();
Handle<Object> receiver = args.receiver(); Handle<Object> receiver = args.receiver();
// Get the object called. // Get the object called.
...@@ -4180,12 +4172,11 @@ MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor( ...@@ -4180,12 +4172,11 @@ MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
&args[0] - 1, &args[0] - 1,
args.length() - 1, args.length() - 1,
is_construct_call); is_construct_call);
v8::Local<v8::Value> value = custom.Call(callback); Handle<Object> result_handle = custom.Call(callback);
if (value.IsEmpty()) { if (result_handle.is_null()) {
result = heap->undefined_value(); result = isolate->heap()->undefined_value();
} else { } else {
result = *reinterpret_cast<Object**>(*value); result = *result_handle;
result->VerifyApiCallResultType();
} }
} }
// Check for exceptions and return result. // Check for exceptions and return result.
......
...@@ -2761,12 +2761,11 @@ RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) { ...@@ -2761,12 +2761,11 @@ RUNTIME_FUNCTION(Runtime_StoreCallbackProperty) {
FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address); FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
DCHECK(fun != NULL); DCHECK(fun != NULL);
LOG(isolate, ApiNamedPropertyAccess("store", *receiver, *name));
Object::ShouldThrow should_throw = Object::ShouldThrow should_throw =
is_sloppy(language_mode) ? Object::DONT_THROW : Object::THROW_ON_ERROR; is_sloppy(language_mode) ? Object::DONT_THROW : Object::THROW_ON_ERROR;
PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver, PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
*holder, should_throw); *holder, should_throw);
custom_args.Call(fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value)); custom_args.Call(fun, name, value);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
return *value; return *value;
} }
...@@ -2796,19 +2795,15 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptorOnly) { ...@@ -2796,19 +2795,15 @@ RUNTIME_FUNCTION(Runtime_LoadPropertyWithInterceptorOnly) {
v8::GenericNamedPropertyGetterCallback getter = v8::GenericNamedPropertyGetterCallback getter =
v8::ToCData<v8::GenericNamedPropertyGetterCallback>( v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
interceptor->getter()); interceptor->getter());
LOG(isolate, ApiNamedPropertyAccess("interceptor-named-get", *holder, *name)); Handle<Object> result = arguments.Call(getter, name);
v8::Local<v8::Value> result =
arguments.Call(getter, v8::Utils::ToLocal(name));
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Handle<Object> result_internal; Handle<Object> result_internal;
if (result.IsEmpty()) { if (result.is_null()) {
return isolate->heap()->no_interceptor_result_sentinel(); return isolate->heap()->no_interceptor_result_sentinel();
} }
result_internal = v8::Utils::OpenHandle(*result); return *result;
result_internal->VerifyApiCallResultType();
return *result_internal;
} }
...@@ -2886,31 +2881,24 @@ RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) { ...@@ -2886,31 +2881,24 @@ RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) {
uint32_t index = args.smi_at(1); uint32_t index = args.smi_at(1);
InterceptorInfo* interceptor = receiver->GetIndexedInterceptor(); InterceptorInfo* interceptor = receiver->GetIndexedInterceptor();
v8::Local<v8::Value> result;
PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver, PropertyCallbackArguments arguments(isolate, interceptor->data(), *receiver,
*receiver, Object::DONT_THROW); *receiver, Object::DONT_THROW);
v8::IndexedPropertyGetterCallback getter = v8::IndexedPropertyGetterCallback getter =
v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
LOG(isolate, Handle<Object> result = arguments.Call(getter, index);
ApiIndexedPropertyAccess("interceptor-indexed-get", *receiver, index));
result = arguments.Call(getter, index);
RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Handle<Object> result_internal; if (result.is_null()) {
if (result.IsEmpty()) {
LookupIterator it(isolate, receiver, index, receiver); LookupIterator it(isolate, receiver, index, receiver);
DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state());
it.Next(); it.Next();
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result_internal, ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
Object::GetProperty(&it)); Object::GetProperty(&it));
} else {
result_internal = v8::Utils::OpenHandle(*result);
result_internal->VerifyApiCallResultType();
} }
return *result_internal; return *result;
} }
......
This diff is collapsed.
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