blob: 57a2d98db11b2bf558691a00cde8ead960943c97 [file] [log] [blame]
Ben Murdochda12d292016-06-02 14:46:10 +01001// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_API_ARGUMENTS_H_
6#define V8_API_ARGUMENTS_H_
7
8#include "src/api.h"
9#include "src/isolate.h"
10#include "src/tracing/trace-event.h"
11#include "src/vm-state-inl.h"
12
13namespace v8 {
14namespace internal {
15
16// Custom arguments replicate a small segment of stack that can be
17// accessed through an Arguments object the same way the actual stack
18// can.
19template <int kArrayLength>
20class CustomArgumentsBase : public Relocatable {
21 public:
22 virtual inline void IterateInstance(ObjectVisitor* v) {
23 v->VisitPointers(values_, values_ + kArrayLength);
24 }
25
26 protected:
27 inline Object** begin() { return values_; }
28 explicit inline CustomArgumentsBase(Isolate* isolate)
29 : Relocatable(isolate) {}
30 Object* values_[kArrayLength];
31};
32
33template <typename T>
34class CustomArguments : public CustomArgumentsBase<T::kArgsLength> {
35 public:
36 static const int kReturnValueOffset = T::kReturnValueIndex;
37
38 typedef CustomArgumentsBase<T::kArgsLength> Super;
39 ~CustomArguments() {
40 this->begin()[kReturnValueOffset] =
41 reinterpret_cast<Object*>(kHandleZapValue);
42 }
43
44 protected:
45 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {}
46
47 template <typename V>
48 Handle<V> GetReturnValue(Isolate* isolate);
49
50 inline Isolate* isolate() {
51 return reinterpret_cast<Isolate*>(this->begin()[T::kIsolateIndex]);
52 }
53};
54
55template <typename T>
56template <typename V>
57Handle<V> CustomArguments<T>::GetReturnValue(Isolate* isolate) {
58 // Check the ReturnValue.
59 Object** handle = &this->begin()[kReturnValueOffset];
60 // Nothing was set, return empty handle as per previous behaviour.
61 if ((*handle)->IsTheHole()) return Handle<V>();
62 Handle<V> result = Handle<V>::cast(Handle<Object>(handle));
63 result->VerifyApiCallResultType();
64 return result;
65}
66
67class PropertyCallbackArguments
68 : public CustomArguments<PropertyCallbackInfo<Value> > {
69 public:
70 typedef PropertyCallbackInfo<Value> T;
71 typedef CustomArguments<T> Super;
72 static const int kArgsLength = T::kArgsLength;
73 static const int kThisIndex = T::kThisIndex;
74 static const int kHolderIndex = T::kHolderIndex;
75 static const int kDataIndex = T::kDataIndex;
76 static const int kReturnValueDefaultValueIndex =
77 T::kReturnValueDefaultValueIndex;
78 static const int kIsolateIndex = T::kIsolateIndex;
79 static const int kShouldThrowOnErrorIndex = T::kShouldThrowOnErrorIndex;
80
81 PropertyCallbackArguments(Isolate* isolate, Object* data, Object* self,
82 JSObject* holder, Object::ShouldThrow should_throw)
83 : Super(isolate) {
84 Object** values = this->begin();
85 values[T::kThisIndex] = self;
86 values[T::kHolderIndex] = holder;
87 values[T::kDataIndex] = data;
88 values[T::kIsolateIndex] = reinterpret_cast<Object*>(isolate);
89 values[T::kShouldThrowOnErrorIndex] =
90 Smi::FromInt(should_throw == Object::THROW_ON_ERROR ? 1 : 0);
91
92 // Here the hole is set as default value.
93 // It cannot escape into js as it's remove in Call below.
94 values[T::kReturnValueDefaultValueIndex] =
95 isolate->heap()->the_hole_value();
96 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
97 DCHECK(values[T::kHolderIndex]->IsHeapObject());
98 DCHECK(values[T::kIsolateIndex]->IsSmi());
99 }
100
101/*
102 * The following Call functions wrap the calling of all callbacks to handle
103 * calling either the old or the new style callbacks depending on which one
104 * has been registered.
105 * For old callbacks which return an empty handle, the ReturnValue is checked
106 * and used if it's been set to anything inside the callback.
107 * New style callbacks always use the return value.
108 */
109 Handle<JSObject> Call(IndexedPropertyEnumeratorCallback f);
110
111#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(F) \
112 F(AccessorNameGetterCallback, "get", v8::Value, Object) \
113 F(GenericNamedPropertyQueryCallback, "has", v8::Integer, Object) \
114 F(GenericNamedPropertyDeleterCallback, "delete", v8::Boolean, Object)
115
116#define WRITE_CALL_1_NAME(Function, type, ApiReturn, InternalReturn) \
117 Handle<InternalReturn> Call(Function f, Handle<Name> name) { \
118 Isolate* isolate = this->isolate(); \
Ben Murdochc5610432016-08-08 18:44:38 +0100119 RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Function); \
Ben Murdochda12d292016-06-02 14:46:10 +0100120 VMState<EXTERNAL> state(isolate); \
121 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
122 PropertyCallbackInfo<ApiReturn> info(begin()); \
123 LOG(isolate, \
124 ApiNamedPropertyAccess("interceptor-named-" type, holder(), *name)); \
125 f(v8::Utils::ToLocal(name), info); \
126 return GetReturnValue<InternalReturn>(isolate); \
127 }
128
129 FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME(WRITE_CALL_1_NAME)
130
131#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_NAME
132#undef WRITE_CALL_1_NAME
133
134#define FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(F) \
135 F(IndexedPropertyGetterCallback, "get", v8::Value, Object) \
136 F(IndexedPropertyQueryCallback, "has", v8::Integer, Object) \
137 F(IndexedPropertyDeleterCallback, "delete", v8::Boolean, Object)
138
139#define WRITE_CALL_1_INDEX(Function, type, ApiReturn, InternalReturn) \
140 Handle<InternalReturn> Call(Function f, uint32_t index) { \
141 Isolate* isolate = this->isolate(); \
Ben Murdochc5610432016-08-08 18:44:38 +0100142 RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Function); \
Ben Murdochda12d292016-06-02 14:46:10 +0100143 VMState<EXTERNAL> state(isolate); \
144 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f)); \
145 PropertyCallbackInfo<ApiReturn> info(begin()); \
146 LOG(isolate, ApiIndexedPropertyAccess("interceptor-indexed-" type, \
147 holder(), index)); \
148 f(index, info); \
149 return GetReturnValue<InternalReturn>(isolate); \
150 }
151
152 FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX(WRITE_CALL_1_INDEX)
153
154#undef FOR_EACH_CALLBACK_TABLE_MAPPING_1_INDEX
155#undef WRITE_CALL_1_INDEX
156
157 Handle<Object> Call(GenericNamedPropertySetterCallback f, Handle<Name> name,
158 Handle<Object> value) {
159 Isolate* isolate = this->isolate();
Ben Murdochc5610432016-08-08 18:44:38 +0100160 RuntimeCallTimerScope timer(
161 isolate, &RuntimeCallStats::GenericNamedPropertySetterCallback);
Ben Murdochda12d292016-06-02 14:46:10 +0100162 VMState<EXTERNAL> state(isolate);
163 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
164 PropertyCallbackInfo<v8::Value> info(begin());
165 LOG(isolate,
166 ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
167 f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
168 return GetReturnValue<Object>(isolate);
169 }
170
171 Handle<Object> Call(IndexedPropertySetterCallback f, uint32_t index,
172 Handle<Object> value) {
173 Isolate* isolate = this->isolate();
Ben Murdochc5610432016-08-08 18:44:38 +0100174 RuntimeCallTimerScope timer(
175 isolate, &RuntimeCallStats::IndexedPropertySetterCallback);
Ben Murdochda12d292016-06-02 14:46:10 +0100176 VMState<EXTERNAL> state(isolate);
177 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
178 PropertyCallbackInfo<v8::Value> info(begin());
179 LOG(isolate,
180 ApiIndexedPropertyAccess("interceptor-indexed-set", holder(), index));
181 f(index, v8::Utils::ToLocal(value), info);
182 return GetReturnValue<Object>(isolate);
183 }
184
185 void Call(AccessorNameSetterCallback f, Handle<Name> name,
186 Handle<Object> value) {
187 Isolate* isolate = this->isolate();
Ben Murdochc5610432016-08-08 18:44:38 +0100188 RuntimeCallTimerScope timer(isolate,
189 &RuntimeCallStats::AccessorNameSetterCallback);
Ben Murdochda12d292016-06-02 14:46:10 +0100190 VMState<EXTERNAL> state(isolate);
191 ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
192 PropertyCallbackInfo<void> info(begin());
193 LOG(isolate,
194 ApiNamedPropertyAccess("interceptor-named-set", holder(), *name));
195 f(v8::Utils::ToLocal(name), v8::Utils::ToLocal(value), info);
196 }
197
198 private:
199 inline JSObject* holder() {
200 return JSObject::cast(this->begin()[T::kHolderIndex]);
201 }
202};
203
204class FunctionCallbackArguments
205 : public CustomArguments<FunctionCallbackInfo<Value> > {
206 public:
207 typedef FunctionCallbackInfo<Value> T;
208 typedef CustomArguments<T> Super;
209 static const int kArgsLength = T::kArgsLength;
210 static const int kHolderIndex = T::kHolderIndex;
211 static const int kDataIndex = T::kDataIndex;
212 static const int kReturnValueDefaultValueIndex =
213 T::kReturnValueDefaultValueIndex;
214 static const int kIsolateIndex = T::kIsolateIndex;
215 static const int kCalleeIndex = T::kCalleeIndex;
216 static const int kContextSaveIndex = T::kContextSaveIndex;
Ben Murdochc5610432016-08-08 18:44:38 +0100217 static const int kNewTargetIndex = T::kNewTargetIndex;
Ben Murdochda12d292016-06-02 14:46:10 +0100218
219 FunctionCallbackArguments(internal::Isolate* isolate, internal::Object* data,
220 internal::HeapObject* callee,
Ben Murdochc5610432016-08-08 18:44:38 +0100221 internal::Object* holder,
222 internal::HeapObject* new_target,
223 internal::Object** argv, int argc)
224 : Super(isolate), argv_(argv), argc_(argc) {
Ben Murdochda12d292016-06-02 14:46:10 +0100225 Object** values = begin();
226 values[T::kDataIndex] = data;
227 values[T::kCalleeIndex] = callee;
228 values[T::kHolderIndex] = holder;
Ben Murdochc5610432016-08-08 18:44:38 +0100229 values[T::kNewTargetIndex] = new_target;
Ben Murdochda12d292016-06-02 14:46:10 +0100230 values[T::kContextSaveIndex] = isolate->heap()->the_hole_value();
231 values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate);
232 // Here the hole is set as default value.
233 // It cannot escape into js as it's remove in Call below.
234 values[T::kReturnValueDefaultValueIndex] =
235 isolate->heap()->the_hole_value();
236 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value();
237 DCHECK(values[T::kCalleeIndex]->IsJSFunction() ||
238 values[T::kCalleeIndex]->IsFunctionTemplateInfo());
239 DCHECK(values[T::kHolderIndex]->IsHeapObject());
240 DCHECK(values[T::kIsolateIndex]->IsSmi());
241 }
242
243 /*
244 * The following Call function wraps the calling of all callbacks to handle
245 * calling either the old or the new style callbacks depending on which one
246 * has been registered.
247 * For old callbacks which return an empty handle, the ReturnValue is checked
248 * and used if it's been set to anything inside the callback.
249 * New style callbacks always use the return value.
250 */
251 Handle<Object> Call(FunctionCallback f);
252
253 private:
254 internal::Object** argv_;
255 int argc_;
Ben Murdochda12d292016-06-02 14:46:10 +0100256};
257
258} // namespace internal
259} // namespace v8
260
261#endif // V8_API_ARGUMENTS_H_