summaryrefslogtreecommitdiff
path: root/deps/v8/src/api-arguments.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/api-arguments.h')
-rw-r--r--deps/v8/src/api-arguments.h254
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_