src: deduplicate CHECK_EQ/CHECK_NE macros
[platform/upstream/nodejs.git] / src / env-inl.h
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #ifndef SRC_ENV_INL_H_
23 #define SRC_ENV_INL_H_
24
25 #include "env.h"
26 #include "node.h"
27 #include "util.h"
28 #include "util-inl.h"
29 #include "uv.h"
30 #include "v8.h"
31
32 #include <stddef.h>
33 #include <stdint.h>
34
35 namespace node {
36
37 inline Environment::GCInfo::GCInfo()
38     : type_(static_cast<v8::GCType>(0)),
39       flags_(static_cast<v8::GCCallbackFlags>(0)),
40       timestamp_(0) {
41 }
42
43 inline Environment::GCInfo::GCInfo(v8::Isolate* isolate,
44                                    v8::GCType type,
45                                    v8::GCCallbackFlags flags,
46                                    uint64_t timestamp)
47     : type_(type),
48       flags_(flags),
49       timestamp_(timestamp) {
50   isolate->GetHeapStatistics(&stats_);
51 }
52
53 inline v8::GCType Environment::GCInfo::type() const {
54   return type_;
55 }
56
57 inline v8::GCCallbackFlags Environment::GCInfo::flags() const {
58   return flags_;
59 }
60
61 inline v8::HeapStatistics* Environment::GCInfo::stats() const {
62   // TODO(bnoordhuis) Const-ify once https://codereview.chromium.org/63693005
63   // lands and makes it way into a stable release.
64   return const_cast<v8::HeapStatistics*>(&stats_);
65 }
66
67 inline uint64_t Environment::GCInfo::timestamp() const {
68   return timestamp_;
69 }
70
71 inline Environment::IsolateData* Environment::IsolateData::Get(
72     v8::Isolate* isolate) {
73   return static_cast<IsolateData*>(isolate->GetData(kIsolateSlot));
74 }
75
76 inline Environment::IsolateData* Environment::IsolateData::GetOrCreate(
77     v8::Isolate* isolate) {
78   IsolateData* isolate_data = Get(isolate);
79   if (isolate_data == NULL) {
80     isolate_data = new IsolateData(isolate);
81     isolate->SetData(kIsolateSlot, isolate_data);
82   }
83   isolate_data->ref_count_ += 1;
84   return isolate_data;
85 }
86
87 inline void Environment::IsolateData::Put() {
88   if (--ref_count_ == 0) {
89     isolate()->SetData(kIsolateSlot, NULL);
90     delete this;
91   }
92 }
93
94 inline Environment::IsolateData::IsolateData(v8::Isolate* isolate)
95     : event_loop_(uv_default_loop()),
96       isolate_(isolate),
97 #define V(PropertyName, StringValue)                                          \
98     PropertyName ## _(isolate, FIXED_ONE_BYTE_STRING(isolate, StringValue)),
99     PER_ISOLATE_STRING_PROPERTIES(V)
100 #undef V
101     ref_count_(0) {
102   QUEUE_INIT(&gc_tracker_queue_);
103 }
104
105 inline uv_loop_t* Environment::IsolateData::event_loop() const {
106   return event_loop_;
107 }
108
109 inline v8::Isolate* Environment::IsolateData::isolate() const {
110   return isolate_;
111 }
112
113 inline Environment::AsyncListener::AsyncListener() {
114   for (int i = 0; i < kFieldsCount; ++i)
115     fields_[i] = 0;
116 }
117
118 inline uint32_t* Environment::AsyncListener::fields() {
119   return fields_;
120 }
121
122 inline int Environment::AsyncListener::fields_count() const {
123   return kFieldsCount;
124 }
125
126 inline bool Environment::AsyncListener::has_listener() const {
127   return fields_[kHasListener] > 0;
128 }
129
130 inline uint32_t Environment::AsyncListener::watched_providers() const {
131   return fields_[kWatchedProviders];
132 }
133
134 inline Environment::DomainFlag::DomainFlag() {
135   for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0;
136 }
137
138 inline uint32_t* Environment::DomainFlag::fields() {
139   return fields_;
140 }
141
142 inline int Environment::DomainFlag::fields_count() const {
143   return kFieldsCount;
144 }
145
146 inline uint32_t Environment::DomainFlag::count() const {
147   return fields_[kCount];
148 }
149
150 inline Environment::TickInfo::TickInfo() : in_tick_(false), last_threw_(false) {
151   for (int i = 0; i < kFieldsCount; ++i)
152     fields_[i] = 0;
153 }
154
155 inline uint32_t* Environment::TickInfo::fields() {
156   return fields_;
157 }
158
159 inline int Environment::TickInfo::fields_count() const {
160   return kFieldsCount;
161 }
162
163 inline bool Environment::TickInfo::in_tick() const {
164   return in_tick_;
165 }
166
167 inline uint32_t Environment::TickInfo::index() const {
168   return fields_[kIndex];
169 }
170
171 inline bool Environment::TickInfo::last_threw() const {
172   return last_threw_;
173 }
174
175 inline uint32_t Environment::TickInfo::length() const {
176   return fields_[kLength];
177 }
178
179 inline void Environment::TickInfo::set_in_tick(bool value) {
180   in_tick_ = value;
181 }
182
183 inline void Environment::TickInfo::set_index(uint32_t value) {
184   fields_[kIndex] = value;
185 }
186
187 inline void Environment::TickInfo::set_last_threw(bool value) {
188   last_threw_ = value;
189 }
190
191 inline Environment* Environment::New(v8::Local<v8::Context> context) {
192   Environment* env = new Environment(context);
193   context->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, env);
194   return env;
195 }
196
197 inline Environment* Environment::GetCurrent(v8::Isolate* isolate) {
198   return GetCurrent(isolate->GetCurrentContext());
199 }
200
201 inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
202   return static_cast<Environment*>(
203       context->GetAlignedPointerFromEmbedderData(kContextEmbedderDataIndex));
204 }
205
206 inline Environment* Environment::GetCurrentChecked(v8::Isolate* isolate) {
207   if (isolate == NULL) {
208     return NULL;
209   } else {
210     return GetCurrentChecked(isolate->GetCurrentContext());
211   }
212 }
213
214 inline Environment* Environment::GetCurrentChecked(
215     v8::Local<v8::Context> context) {
216   if (context.IsEmpty()) {
217     return NULL;
218   } else {
219     return GetCurrent(context);
220   }
221 }
222
223 inline Environment::Environment(v8::Local<v8::Context> context)
224     : isolate_(context->GetIsolate()),
225       isolate_data_(IsolateData::GetOrCreate(context->GetIsolate())),
226       using_smalloc_alloc_cb_(false),
227       using_domains_(false),
228       printed_error_(false),
229       context_(context->GetIsolate(), context) {
230   // We'll be creating new objects so make sure we've entered the context.
231   v8::HandleScope handle_scope(isolate());
232   v8::Context::Scope context_scope(context);
233   set_binding_cache_object(v8::Object::New(isolate()));
234   set_module_load_list_array(v8::Array::New(isolate()));
235   RB_INIT(&cares_task_list_);
236   QUEUE_INIT(&gc_tracker_queue_);
237 }
238
239 inline Environment::~Environment() {
240   v8::HandleScope handle_scope(isolate());
241
242   context()->SetAlignedPointerInEmbedderData(kContextEmbedderDataIndex, NULL);
243 #define V(PropertyName, TypeName) PropertyName ## _.Reset();
244   ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
245 #undef V
246   isolate_data()->Put();
247 }
248
249 inline void Environment::Dispose() {
250   delete this;
251 }
252
253 inline v8::Isolate* Environment::isolate() const {
254   return isolate_;
255 }
256
257 inline bool Environment::has_async_listener() const {
258   // The const_cast is okay, it doesn't violate conceptual const-ness.
259   return const_cast<Environment*>(this)->async_listener()->has_listener();
260 }
261
262 inline uint32_t Environment::watched_providers() const {
263   // The const_cast is okay, it doesn't violate conceptual const-ness.
264   return const_cast<Environment*>(this)->async_listener()->watched_providers();
265 }
266
267 inline bool Environment::in_domain() const {
268   // The const_cast is okay, it doesn't violate conceptual const-ness.
269   return using_domains() &&
270          const_cast<Environment*>(this)->domain_flag()->count() > 0;
271 }
272
273 inline Environment* Environment::from_immediate_check_handle(
274     uv_check_t* handle) {
275   return CONTAINER_OF(handle, Environment, immediate_check_handle_);
276 }
277
278 inline uv_check_t* Environment::immediate_check_handle() {
279   return &immediate_check_handle_;
280 }
281
282 inline uv_idle_t* Environment::immediate_idle_handle() {
283   return &immediate_idle_handle_;
284 }
285
286 inline Environment* Environment::from_idle_prepare_handle(
287     uv_prepare_t* handle) {
288   return CONTAINER_OF(handle, Environment, idle_prepare_handle_);
289 }
290
291 inline uv_prepare_t* Environment::idle_prepare_handle() {
292   return &idle_prepare_handle_;
293 }
294
295 inline Environment* Environment::from_idle_check_handle(uv_check_t* handle) {
296   return CONTAINER_OF(handle, Environment, idle_check_handle_);
297 }
298
299 inline uv_check_t* Environment::idle_check_handle() {
300   return &idle_check_handle_;
301 }
302
303 inline uv_loop_t* Environment::event_loop() const {
304   return isolate_data()->event_loop();
305 }
306
307 inline Environment::AsyncListener* Environment::async_listener() {
308   return &async_listener_count_;
309 }
310
311 inline Environment::DomainFlag* Environment::domain_flag() {
312   return &domain_flag_;
313 }
314
315 inline Environment::TickInfo* Environment::tick_info() {
316   return &tick_info_;
317 }
318
319 inline bool Environment::using_smalloc_alloc_cb() const {
320   return using_smalloc_alloc_cb_;
321 }
322
323 inline void Environment::set_using_smalloc_alloc_cb(bool value) {
324   using_smalloc_alloc_cb_ = value;
325 }
326
327 inline bool Environment::using_domains() const {
328   return using_domains_;
329 }
330
331 inline void Environment::set_using_domains(bool value) {
332   using_domains_ = value;
333 }
334
335 inline bool Environment::printed_error() const {
336   return printed_error_;
337 }
338
339 inline void Environment::set_printed_error(bool value) {
340   printed_error_ = value;
341 }
342
343 inline Environment* Environment::from_cares_timer_handle(uv_timer_t* handle) {
344   return CONTAINER_OF(handle, Environment, cares_timer_handle_);
345 }
346
347 inline uv_timer_t* Environment::cares_timer_handle() {
348   return &cares_timer_handle_;
349 }
350
351 inline ares_channel Environment::cares_channel() {
352   return cares_channel_;
353 }
354
355 // Only used in the call to ares_init_options().
356 inline ares_channel* Environment::cares_channel_ptr() {
357   return &cares_channel_;
358 }
359
360 inline ares_task_list* Environment::cares_task_list() {
361   return &cares_task_list_;
362 }
363
364 inline Environment::IsolateData* Environment::isolate_data() const {
365   return isolate_data_;
366 }
367
368 // this would have been a template function were it not for the fact that g++
369 // sometimes fails to resolve it...
370 #define THROW_ERROR(fun)                                                      \
371   do {                                                                        \
372     v8::HandleScope scope(isolate);                                           \
373     isolate->ThrowException(fun(OneByteString(isolate, errmsg)));             \
374   }                                                                           \
375   while (0)
376
377 inline void Environment::ThrowError(v8::Isolate* isolate, const char* errmsg) {
378   THROW_ERROR(v8::Exception::Error);
379 }
380
381 inline void Environment::ThrowTypeError(v8::Isolate* isolate,
382                                         const char* errmsg) {
383   THROW_ERROR(v8::Exception::TypeError);
384 }
385
386 inline void Environment::ThrowRangeError(v8::Isolate* isolate,
387                                          const char* errmsg) {
388   THROW_ERROR(v8::Exception::RangeError);
389 }
390
391 inline void Environment::ThrowError(const char* errmsg) {
392   ThrowError(isolate(), errmsg);
393 }
394
395 inline void Environment::ThrowTypeError(const char* errmsg) {
396   ThrowTypeError(isolate(), errmsg);
397 }
398
399 inline void Environment::ThrowRangeError(const char* errmsg) {
400   ThrowRangeError(isolate(), errmsg);
401 }
402
403 inline void Environment::ThrowErrnoException(int errorno,
404                                              const char* syscall,
405                                              const char* message,
406                                              const char* path) {
407   isolate()->ThrowException(
408       ErrnoException(isolate(), errorno, syscall, message, path));
409 }
410
411 inline void Environment::ThrowUVException(int errorno,
412                                           const char* syscall,
413                                           const char* message,
414                                           const char* path) {
415   isolate()->ThrowException(
416       UVException(isolate(), errorno, syscall, message, path));
417 }
418
419 #define V(PropertyName, StringValue)                                          \
420   inline                                                                      \
421   v8::Local<v8::String> Environment::IsolateData::PropertyName() const {      \
422     /* Strings are immutable so casting away const-ness here is okay. */      \
423     return const_cast<IsolateData*>(this)->PropertyName ## _.Get(isolate());  \
424   }
425   PER_ISOLATE_STRING_PROPERTIES(V)
426 #undef V
427
428 #define V(PropertyName, StringValue)                                          \
429   inline v8::Local<v8::String> Environment::PropertyName() const {            \
430     return isolate_data()->PropertyName();                                    \
431   }
432   PER_ISOLATE_STRING_PROPERTIES(V)
433 #undef V
434
435 #define V(PropertyName, TypeName)                                             \
436   inline v8::Local<TypeName> Environment::PropertyName() const {              \
437     return StrongPersistentToLocal(PropertyName ## _);                        \
438   }                                                                           \
439   inline void Environment::set_ ## PropertyName(v8::Local<TypeName> value) {  \
440     PropertyName ## _.Reset(isolate(), value);                                \
441   }
442   ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V)
443 #undef V
444
445 #undef ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES
446 #undef PER_ISOLATE_STRING_PROPERTIES
447
448 }  // namespace node
449
450 #endif  // SRC_ENV_INL_H_