diff options
Diffstat (limited to 'deps/v8/src/api-arguments.h')
-rw-r--r-- | deps/v8/src/api-arguments.h | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/deps/v8/src/api-arguments.h b/deps/v8/src/api-arguments.h new file mode 100644 index 0000000000..3bfe34dc89 --- /dev/null +++ b/deps/v8/src/api-arguments.h @@ -0,0 +1,254 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_API_ARGUMENTS_H_ +#define V8_API_ARGUMENTS_H_ + +#include "src/api.h" +#include "src/isolate.h" +#include "src/tracing/trace-event.h" +#include "src/vm-state-inl.h" + +namespace v8 { +namespace internal { + +// Custom arguments replicate a small segment of stack that can be +// accessed through an Arguments object the same way the actual stack +// can. +template <int kArrayLength> +class CustomArgumentsBase : public Relocatable { + public: + virtual inline void IterateInstance(ObjectVisitor* v) { + v->VisitPointers(values_, values_ + kArrayLength); + } + + protected: + inline Object** begin() { return values_; } + explicit inline CustomArgumentsBase(Isolate* isolate) + : Relocatable(isolate) {} + Object* values_[kArrayLength]; +}; + +template <typename T> +class CustomArguments : public CustomArgumentsBase<T::kArgsLength> { + public: + static const int kReturnValueOffset = T::kReturnValueIndex; + + typedef CustomArgumentsBase<T::kArgsLength> Super; + ~CustomArguments() { + this->begin()[kReturnValueOffset] = + reinterpret_cast<Object*>(kHandleZapValue); + } + + protected: + explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {} + + template <typename V> + Handle<V> GetReturnValue(Isolate* isolate); + + inline Isolate* isolate() { + 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 + : public CustomArguments<PropertyCallbackInfo<Value> > { + public: + typedef PropertyCallbackInfo<Value> T; + typedef CustomArguments<T> Super; + static const int kArgsLength = T::kArgsLength; + static const int kThisIndex = T::kThisIndex; + static const int kHolderIndex = T::kHolderIndex; + static const int kDataIndex = T::kDataIndex; + static const int kReturnValueDefaultValueIndex = + T::kReturnValueDefaultValueIndex; + static const int kIsolateIndex = T::kIsolateIndex; + static const int kShouldThrowOnErrorIndex = T::kShouldThrowOnErrorIndex; + + PropertyCallbackArguments(Isolate* isolate, Object* data, Object* self, + JSObject* holder, Object::ShouldThrow should_throw) + : Super(isolate) { + Object** values = this->begin(); + values[T::kThisIndex] = self; + values[T::kHolderIndex] = holder; + values[T::kDataIndex] = data; + values[T::kIsolateIndex] = reinterpret_cast<Object*>(isolate); + values[T::kShouldThrowOnErrorIndex] = + Smi::FromInt(should_throw == Object::THROW_ON_ERROR ? 1 : 0); + + // Here the hole is set as default value. + // It cannot escape into js as it's remove in Call below. + values[T::kReturnValueDefaultValueIndex] = + isolate->heap()->the_hole_value(); + values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); + DCHECK(values[T::kHolderIndex]->IsHeapObject()); + DCHECK(values[T::kIsolateIndex]->IsSmi()); + } + +/* + * The following Call functions wrap the calling of all callbacks to handle + * calling either the old or the new style callbacks depending on which one + * has been registered. + * For old callbacks which return an empty handle, the ReturnValue is checked + * and used if it's been set to anything inside the callback. + * New style callbacks always use the return value. + */ + Handle<JSObject> Call(IndexedPropertyEnumeratorCallback 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); \ + } + + FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(WRITE_CALL_1_NAME) + +#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); \ + } + + FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(WRITE_CALL_1_INDEX) + +#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); + } + + Handle<Object> Call(IndexedPropertySetterCallback f, uint32_t index, + 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); + } + + void Call(AccessorNameSetterCallback f, Handle<Name> name, + Handle<Object> value) { + Isolate* isolate = this->isolate(); + 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); + } + + private: + inline JSObject* holder() { + return JSObject::cast(this->begin()[T::kHolderIndex]); + } +}; + +class FunctionCallbackArguments + : public CustomArguments<FunctionCallbackInfo<Value> > { + public: + typedef FunctionCallbackInfo<Value> T; + typedef CustomArguments<T> Super; + static const int kArgsLength = T::kArgsLength; + static const int kHolderIndex = T::kHolderIndex; + static const int kDataIndex = T::kDataIndex; + static const int kReturnValueDefaultValueIndex = + T::kReturnValueDefaultValueIndex; + static const int kIsolateIndex = T::kIsolateIndex; + static const int kCalleeIndex = T::kCalleeIndex; + static const int kContextSaveIndex = T::kContextSaveIndex; + + FunctionCallbackArguments(internal::Isolate* isolate, internal::Object* data, + internal::HeapObject* callee, + internal::Object* holder, internal::Object** argv, + int argc, bool is_construct_call) + : Super(isolate), + argv_(argv), + argc_(argc), + is_construct_call_(is_construct_call) { + Object** values = begin(); + values[T::kDataIndex] = data; + values[T::kCalleeIndex] = callee; + values[T::kHolderIndex] = holder; + values[T::kContextSaveIndex] = isolate->heap()->the_hole_value(); + values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate); + // Here the hole is set as default value. + // It cannot escape into js as it's remove in Call below. + values[T::kReturnValueDefaultValueIndex] = + isolate->heap()->the_hole_value(); + values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); + DCHECK(values[T::kCalleeIndex]->IsJSFunction() || + values[T::kCalleeIndex]->IsFunctionTemplateInfo()); + DCHECK(values[T::kHolderIndex]->IsHeapObject()); + DCHECK(values[T::kIsolateIndex]->IsSmi()); + } + + /* + * The following Call function wraps the calling of all callbacks to handle + * calling either the old or the new style callbacks depending on which one + * has been registered. + * For old callbacks which return an empty handle, the ReturnValue is checked + * and used if it's been set to anything inside the callback. + * New style callbacks always use the return value. + */ + Handle<Object> Call(FunctionCallback f); + + private: + internal::Object** argv_; + int argc_; + bool is_construct_call_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_API_ARGUMENTS_H_ |