OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 int length() const { return length_; } | 75 int length() const { return length_; } |
76 | 76 |
77 Object** arguments() { return arguments_; } | 77 Object** arguments() { return arguments_; } |
78 | 78 |
79 private: | 79 private: |
80 int length_; | 80 int length_; |
81 Object** arguments_; | 81 Object** arguments_; |
82 }; | 82 }; |
83 | 83 |
84 | 84 |
| 85 #define FOR_EACH_CALLBACK_TABLE_MAPPING(F) \ |
| 86 F(AccessorGetter, AccessorGetterCallback) \ |
| 87 F(AccessorSetter, AccessorSetterCallback) \ |
| 88 F(InvocationCallback, FunctionCallback) \ |
| 89 F(NamedPropertySetter, NamedPropertySetterCallback) \ |
| 90 F(NamedPropertyQuery, NamedPropertyQueryCallback) \ |
| 91 F(NamedPropertyDeleter, NamedPropertyDeleterCallback) \ |
| 92 F(IndexedPropertyGetter, IndexedPropertyGetterCallback) \ |
| 93 F(IndexedPropertySetter, IndexedPropertySetterCallback) \ |
| 94 F(IndexedPropertyQuery, IndexedPropertyQueryCallback) \ |
| 95 F(IndexedPropertyDeleter, IndexedPropertyDeleterCallback) \ |
| 96 F(IndexedPropertyEnumerator, IndexedPropertyEnumeratorCallback) \ |
| 97 |
| 98 // These aren't included in the list as they have duplicate signatures |
| 99 // F(NamedPropertyEnumerator, NamedPropertyEnumeratorCallback) \ |
| 100 // F(NamedPropertyGetter, NamedPropertyGetterCallback) \ |
| 101 |
| 102 // TODO(dcarney): Remove this class when old callbacks are gone. |
| 103 class CallbackTable { |
| 104 public: |
| 105 // TODO(dcarney): Flip this when it makes sense for performance. |
| 106 static const bool kStoreVoidFunctions = true; |
| 107 static inline bool ReturnsVoid(Isolate* isolate, void* function) { |
| 108 CallbackTable* table = isolate->callback_table(); |
| 109 bool contains = |
| 110 table != NULL && |
| 111 table->map_.occupancy() != 0 && |
| 112 table->Contains(function); |
| 113 return contains == kStoreVoidFunctions; |
| 114 } |
| 115 |
| 116 #define WRITE_REGISTER(OldFunction, NewFunction) \ |
| 117 static OldFunction Register(Isolate* isolate, NewFunction f) { \ |
| 118 InsertCallback(isolate, reinterpret_cast<void*>(f), true); \ |
| 119 return reinterpret_cast<OldFunction>(f); \ |
| 120 } \ |
| 121 \ |
| 122 static OldFunction Register(Isolate* isolate, OldFunction f) { \ |
| 123 InsertCallback(isolate, reinterpret_cast<void*>(f), false); \ |
| 124 return f; \ |
| 125 } |
| 126 FOR_EACH_CALLBACK_TABLE_MAPPING(WRITE_REGISTER) |
| 127 #undef WRITE_REGISTER |
| 128 |
| 129 private: |
| 130 CallbackTable(): map_(Match, 64) {} |
| 131 typedef HashMap::Entry Entry; |
| 132 static bool Match(void* a, void* b) { |
| 133 return a == b; |
| 134 } |
| 135 static uint32_t Hash(void* function) { |
| 136 uintptr_t as_int = reinterpret_cast<uintptr_t>(function); |
| 137 if (sizeof(function) == 4) return static_cast<uint32_t>(as_int); |
| 138 uint64_t as_64 = static_cast<uint64_t>(as_int); |
| 139 return |
| 140 static_cast<uint32_t>(as_64 >> 32) ^ |
| 141 static_cast<uint32_t>(as_64); |
| 142 } |
| 143 bool Contains(void* function) { |
| 144 ASSERT(function != NULL); |
| 145 return map_.Lookup(function, Hash(function), false) != NULL; |
| 146 } |
| 147 static void InsertCallback(Isolate* isolate, |
| 148 void* function, |
| 149 bool returns_void) { |
| 150 if (function == NULL) return; |
| 151 // Don't store for performance. |
| 152 if (kStoreVoidFunctions != returns_void) return; |
| 153 CallbackTable* table = isolate->callback_table(); |
| 154 if (table == NULL) { |
| 155 table = new CallbackTable(); |
| 156 isolate->set_callback_table(table); |
| 157 } |
| 158 table->Insert(function); |
| 159 } |
| 160 void Insert(void* function) { |
| 161 ASSERT(function != NULL); |
| 162 Entry* entry = map_.Lookup(function, Hash(function), true); |
| 163 ASSERT(entry != NULL); |
| 164 ASSERT(entry->value == NULL || entry->value == function); |
| 165 entry->value = function; |
| 166 } |
| 167 HashMap map_; |
| 168 DISALLOW_COPY_AND_ASSIGN(CallbackTable); |
| 169 }; |
| 170 |
| 171 |
85 // Custom arguments replicate a small segment of stack that can be | 172 // Custom arguments replicate a small segment of stack that can be |
86 // accessed through an Arguments object the same way the actual stack | 173 // accessed through an Arguments object the same way the actual stack |
87 // can. | 174 // can. |
88 class CustomArguments : public Relocatable { | 175 template<int kArrayLength> |
89 public: | 176 class CustomArgumentsBase : public Relocatable { |
90 inline CustomArguments(Isolate* isolate, | 177 public: |
91 Object* data, | 178 virtual inline void IterateInstance(ObjectVisitor* v) { |
92 Object* self, | 179 v->VisitPointers(values_, values_ + kArrayLength); |
93 JSObject* holder) : Relocatable(isolate) { | 180 } |
94 ASSERT(reinterpret_cast<Object*>(isolate)->IsSmi()); | 181 protected: |
95 values_[3] = self; | 182 inline Object** end() { return values_ + kArrayLength - 1; } |
96 values_[2] = holder; | 183 explicit inline CustomArgumentsBase(Isolate* isolate) |
97 values_[1] = data; | 184 : Relocatable(isolate) {} |
98 values_[0] = reinterpret_cast<Object*>(isolate); | 185 Object* values_[kArrayLength]; |
99 } | 186 }; |
100 | 187 |
101 inline explicit CustomArguments(Isolate* isolate) : Relocatable(isolate) { | 188 |
102 #ifdef DEBUG | 189 template<typename T> |
103 for (size_t i = 0; i < ARRAY_SIZE(values_); i++) { | 190 class CustomArguments : public CustomArgumentsBase<T::kArgsLength> { |
104 values_[i] = reinterpret_cast<Object*>(kZapValue); | 191 public: |
| 192 static const int kReturnValueOffset = T::kReturnValueIndex; |
| 193 |
| 194 typedef CustomArgumentsBase<T::kArgsLength> Super; |
| 195 ~CustomArguments() { |
| 196 // TODO(dcarney): create a new zap value for this. |
| 197 this->end()[kReturnValueOffset] = |
| 198 reinterpret_cast<Object*>(kHandleZapValue); |
| 199 } |
| 200 |
| 201 #define WRITE_CALLBACK_RESULT(OldFunction, NewFunction) \ |
| 202 template<typename V> \ |
| 203 inline v8::Handle<V> GetCallbackResult(Isolate* isolate, \ |
| 204 OldFunction function, \ |
| 205 v8::Handle<V> call_result) { \ |
| 206 return GetCallbackResult(isolate, \ |
| 207 reinterpret_cast<void*>(function), \ |
| 208 call_result); \ |
| 209 } |
| 210 FOR_EACH_CALLBACK_TABLE_MAPPING(WRITE_CALLBACK_RESULT) |
| 211 #undef WRITE_CALLBACK_RESULT |
| 212 |
| 213 protected: |
| 214 template<typename V> |
| 215 inline v8::Handle<V> GetCallbackResult(Isolate* isolate, |
| 216 void* function, |
| 217 v8::Handle<V> call_result) { |
| 218 // For non-void calls, return the result only if call_result is set. |
| 219 if (!CallbackTable::ReturnsVoid(isolate, function) && |
| 220 !call_result.IsEmpty()) { |
| 221 return call_result; |
105 } | 222 } |
106 #endif | 223 // Check the ReturnValue. |
107 } | 224 Object* object = this->end()[kReturnValueOffset]; |
108 | 225 // Nothing was set, return empty handle as per previous behaviour. |
109 void IterateInstance(ObjectVisitor* v); | 226 if (object->IsTheHole()) return v8::Handle<V>(); |
110 Object** end() { return values_ + ARRAY_SIZE(values_) - 1; } | 227 // We shouldn't need this, but play it safe for now. |
111 | 228 // TODO(dcarney) Remove once all calls to this are verified as safe?? |
112 private: | 229 return v8::Local<V>::New(reinterpret_cast<v8::Isolate*>(isolate), |
113 Object* values_[4]; | 230 v8::Handle<V>(reinterpret_cast<V*>(&object))); |
114 }; | 231 } |
115 | 232 |
116 | 233 explicit inline CustomArguments(Isolate* isolate) : Super(isolate) {} |
| 234 }; |
| 235 |
| 236 |
| 237 class PropertyCallbackArguments |
| 238 : public CustomArguments<PropertyCallbackInfo<Value> > { |
| 239 public: |
| 240 typedef PropertyCallbackInfo<Value> T; |
| 241 typedef CustomArguments<T> Super; |
| 242 static const int kArgsLength = T::kArgsLength; |
| 243 static const int kThisIndex = T::kThisIndex; |
| 244 static const int kHolderIndex = T::kHolderIndex; |
| 245 |
| 246 PropertyCallbackArguments(Isolate* isolate, |
| 247 Object* data, |
| 248 Object* self, |
| 249 JSObject* holder) |
| 250 : Super(isolate) { |
| 251 Object** values = this->end(); |
| 252 values[T::kThisIndex] = self; |
| 253 values[T::kHolderIndex] = holder; |
| 254 values[T::kDataIndex] = data; |
| 255 values[T::kIsolateIndex] = reinterpret_cast<Object*>(isolate); |
| 256 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); |
| 257 ASSERT(values[T::kHolderIndex]->IsHeapObject()); |
| 258 ASSERT(values[T::kIsolateIndex]->IsSmi()); |
| 259 } |
| 260 |
| 261 inline v8::AccessorInfo NewInfo() { |
| 262 return v8::AccessorInfo(end()); |
| 263 } |
| 264 }; |
| 265 |
| 266 |
| 267 class FunctionCallbackArguments |
| 268 : public CustomArguments<FunctionCallbackInfo<Value> > { |
| 269 public: |
| 270 typedef FunctionCallbackInfo<Value> T; |
| 271 typedef CustomArguments<T> Super; |
| 272 static const int kArgsLength = T::kArgsLength; |
| 273 |
| 274 FunctionCallbackArguments(internal::Isolate* isolate, |
| 275 internal::Object* data, |
| 276 internal::JSFunction* callee, |
| 277 internal::Object* holder) |
| 278 : Super(isolate) { |
| 279 Object** values = end(); |
| 280 values[T::kDataIndex] = data; |
| 281 values[T::kCalleeIndex] = callee; |
| 282 values[T::kHolderIndex] = holder; |
| 283 values[T::kIsolateIndex] = reinterpret_cast<internal::Object*>(isolate); |
| 284 values[T::kReturnValueIndex] = isolate->heap()->the_hole_value(); |
| 285 ASSERT(values[T::kCalleeIndex]->IsJSFunction()); |
| 286 ASSERT(values[T::kHolderIndex]->IsHeapObject()); |
| 287 ASSERT(values[T::kIsolateIndex]->IsSmi()); |
| 288 } |
| 289 |
| 290 inline v8::Arguments NewArguments(internal::Object** argv, |
| 291 int argc, |
| 292 bool is_construct_call) { |
| 293 return v8::Arguments(this->end(), argv, argc, is_construct_call); |
| 294 } |
| 295 }; |
| 296 |
| 297 |
117 #define DECLARE_RUNTIME_FUNCTION(Type, Name) \ | 298 #define DECLARE_RUNTIME_FUNCTION(Type, Name) \ |
118 Type Name(Arguments args, Isolate* isolate) | 299 Type Name(Arguments args, Isolate* isolate) |
119 | 300 |
120 | 301 |
121 #define RUNTIME_FUNCTION(Type, Name) \ | 302 #define RUNTIME_FUNCTION(Type, Name) \ |
122 Type Name(Arguments args, Isolate* isolate) | 303 Type Name(Arguments args, Isolate* isolate) |
123 | 304 |
124 | 305 |
125 #define RUNTIME_ARGUMENTS(isolate, args) args, isolate | 306 #define RUNTIME_ARGUMENTS(isolate, args) args, isolate |
126 | 307 |
127 | 308 |
128 } } // namespace v8::internal | 309 } } // namespace v8::internal |
129 | 310 |
130 #endif // V8_ARGUMENTS_H_ | 311 #endif // V8_ARGUMENTS_H_ |
OLD | NEW |