• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_ECMA_MACROS_H
17 #define ECMASCRIPT_ECMA_MACROS_H
18 
19 #include "ecmascript/common.h"
20 #include "ecmascript/log_wrapper.h"
21 
22 #if defined(ENABLE_BYTRACE)
23     #include "hitrace_meter.h"
24 #endif
25 
26 #if defined(__cplusplus)
27 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
28 
29 #define OPTIONAL_LOG(vm, level) LOG_ECMA_IF(vm->IsOptionalLogEnabled(), level)
30 #define OPTIONAL_LOG_COMPILER(level) LOG_ECMA_IF(IsLogEnabled(), level)
31 
32 #if !defined(ENABLE_BYTRACE)
33     #define ECMA_BYTRACE_NAME(tag, name)
34 #else
35     #define ECMA_BYTRACE_NAME(tag, name) HITRACE_METER_NAME(tag, name)
36 #endif
37 
38 #if defined(ENABLE_HITRACE)
39     #define ENQUEUE_JOB_HITRACE(pendingJob, queueType) job::EnqueueJobScope hitraceScope(pendingJob, queueType)
40     #define EXECUTE_JOB_HITRACE(pendingJob) job::ExecuteJobScope hitraceScope(pendingJob)
41 #else
42     #define ENQUEUE_JOB_HITRACE(pendingJob, queueType)
43     #define EXECUTE_JOB_HITRACE(pendingJob)
44 #endif
45 
46 /* Note: We can't statically decide the element type is a primitive or heap object, especially for */
47 /*       dynamically-typed languages like JavaScript. So we simply skip the read-barrier.          */
48 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
49 #define GET_VALUE(addr, offset) Barriers::GetValue<JSTaggedType>((addr), (offset))
50 
51 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
52 #define SET_VALUE_WITH_BARRIER(thread, addr, offset, value)                          \
53     if ((value).IsHeapObject()) {                                                    \
54         Barriers::SetObject<true>(thread, addr, offset, (value).GetRawData());    \
55     } else {                                                                         \
56         Barriers::SetPrimitive<JSTaggedType>(addr, offset, (value).GetRawData()); \
57     }
58 
59 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
60 #define SET_VALUE_PRIMITIVE(addr, offset, value) \
61     Barriers::SetPrimitive<JSTaggedType>(this, offset, (value).GetRawData())
62 
63 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
64 #define ACCESSORS(name, offset, endOffset)                                                                    \
65     static constexpr size_t endOffset = (offset) + JSTaggedValue::TaggedTypeSize();                           \
66     JSTaggedValue Get##name() const                                                                           \
67     {                                                                                                         \
68         /* Note: We can't statically decide the element type is a primitive or heap object, especially for */ \
69         /*       dynamically-typed languages like JavaScript. So we simply skip the read-barrier.          */ \
70         return JSTaggedValue(Barriers::GetValue<JSTaggedType>(this, offset));                              \
71     }                                                                                                         \
72     template<typename T>                                                                                      \
73     void Set##name(const JSThread *thread, JSHandle<T> value, BarrierMode mode = WRITE_BARRIER)               \
74     {                                                                                                         \
75         if (mode == WRITE_BARRIER) {                                                                          \
76             if (value.GetTaggedValue().IsHeapObject()) {                                                      \
77                 Barriers::SetObject<true>(thread, this, offset, value.GetTaggedValue().GetRawData());      \
78             } else {                                                                                          \
79                 Barriers::SetPrimitive<JSTaggedType>(this, offset, value.GetTaggedValue().GetRawData());   \
80             }                                                                                                 \
81         } else {                                                                                              \
82             Barriers::SetPrimitive<JSTaggedType>(this, offset, value.GetTaggedValue().GetRawData());       \
83         }                                                                                                     \
84     }                                                                                                         \
85     void Set##name(const JSThread *thread, JSTaggedValue value, BarrierMode mode = WRITE_BARRIER)             \
86     {                                                                                                         \
87         if (mode == WRITE_BARRIER) {                                                                          \
88             if (value.IsHeapObject()) {                                                                       \
89                 Barriers::SetObject<true>(thread, this, offset, value.GetRawData());                       \
90             } else {                                                                                          \
91                 Barriers::SetPrimitive<JSTaggedType>(this, offset, value.GetRawData());                    \
92             }                                                                                                 \
93         } else {                                                                                              \
94             Barriers::SetPrimitive<JSTaggedType>(this, offset, value.GetRawData());                        \
95         }                                                                                                     \
96     }
97 
98 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
99 #define DEFINE_ALIGN_SIZE(offset) \
100     static constexpr size_t SIZE = ((offset) + sizeof(JSTaggedType) - 1U) & (~(sizeof(JSTaggedType) - 1U))
101 
102 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
103 #define ACCESSORS_FIXED_SIZE_FIELD(name, type, sizeType, offset, endOffset) \
104     static_assert(sizeof(type) <= sizeof(sizeType));                        \
105     static constexpr size_t endOffset = (offset) + sizeof(sizeType);        \
106     inline void Set##name(type value)                                       \
107     {                                                                       \
108         Barriers::SetPrimitive<type>(this, offset, value);               \
109     }                                                                       \
110     inline type Get##name() const                                           \
111     {                                                                       \
112         return Barriers::GetValue<type>(this, offset);                   \
113     }
114 
115 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
116 #define ACCESSORS_NATIVE_FIELD(name, type, offset, endOffset) \
117     ACCESSORS_FIXED_SIZE_FIELD(name, type *, type *, offset, endOffset)
118 
119 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
120 #define ACCESSORS_PRIMITIVE_FIELD(name, type, offset, endOffset) \
121     ACCESSORS_FIXED_SIZE_FIELD(name, type, type, offset, endOffset)
122 
123 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
124 #define ACCESSORS_BIT_FIELD(name, offset, endOffset)                        \
125     ACCESSORS_FIXED_SIZE_FIELD(name, uint32_t, uint32_t, offset, endOffset) \
126     inline void Clear##name()                                               \
127     {                                                                       \
128         Set##name(0UL);                                                     \
129     }
130 
131 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
132 #define SET_GET_BIT_FIELD(bitFieldName, name, type)                    \
133     inline type Get##name() const                                      \
134     {                                                                  \
135         return name##Bits::Decode(Get##bitFieldName());                \
136     }                                                                  \
137     inline void Set##name(type t)                                      \
138     {                                                                  \
139         Set##bitFieldName(name##Bits::Update(Get##bitFieldName(), t)); \
140     }
141 
142 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
143 #define FIRST_BIT_FIELD(bitFieldName, name, type, bits) \
144     using name##Bits = BitField<type, 0, bits>;         \
145     SET_GET_BIT_FIELD(bitFieldName, name, type)
146 
147 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
148 #define NEXT_BIT_FIELD(bitFieldName, name, type, bits, lastName) \
149     using name##Bits = lastName##Bits::NextField<type, bits>;    \
150     SET_GET_BIT_FIELD(bitFieldName, name, type)
151 
152 #if !defined(NDEBUG)
153 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
154 #define DASSERT(cond) assert(cond)
155 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
156 #define DASSERT_PRINT(cond, message)                     \
157     if (auto cond_val = (cond); UNLIKELY(!(cond_val))) { \
158         std::cerr << (message) << std::endl;             \
159         ASSERT(#cond &&cond_val);                        \
160     }
161 #else                                                      // NDEBUG
162 #define DASSERT(cond) static_cast<void>(0)                 // NOLINT(cppcoreguidelines-macro-usage)
163 #define DASSERT_PRINT(cond, message) static_cast<void>(0)  // NOLINT(cppcoreguidelines-macro-usage)
164 #endif                                                     // !NDEBUG
165 
166 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
167 #define RASSERT(cond) assert(cond)
168 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
169 #define RASSERT_PRINT(cond, message)                   \
170     if (auto cond_val = cond; UNLIKELY(!(cond_val))) { \
171         std::cerr << message << std::endl;             \
172         RASSERT(#cond &&cond_val);                     \
173     }
174 
175 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
176 #define RETURN_IF_ABRUPT_COMPLETION(thread)  \
177     do {                                     \
178         if ((thread)->HasPendingException()) { \
179             return;                          \
180         }                                    \
181     } while (false)
182 
183 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
184 #define RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, value) \
185     do {                                                 \
186         if ((thread)->HasPendingException()) {           \
187             return (value);                              \
188         }                                                \
189     } while (false)
190 
191 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
192 #define RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread) \
193     do {                                              \
194         if ((thread)->HasPendingException()) {        \
195             return JSTaggedValue::Exception();        \
196         }                                             \
197     } while (false)
198 
199 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
200 #define RETURN_HANDLE_IF_ABRUPT_COMPLETION(type, thread)               \
201     do {                                                               \
202         if ((thread)->HasPendingException()) {                         \
203             return JSHandle<type>(thread, JSTaggedValue::Exception()); \
204         }                                                              \
205     } while (false)
206 
207 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
208 #define ASSERT_NO_ABRUPT_COMPLETION(thread) ASSERT(!(thread)->HasPendingException());
209 
210 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
211 #define SET_DATE_VALUE(name, code, isLocal)                                                       \
212     static JSTaggedValue name(EcmaRuntimeCallInfo *argv)                                          \
213     {                                                                                             \
214         ASSERT(argv);                                                                             \
215         JSThread *thread = argv->GetThread();                                                     \
216         JSHandle<JSTaggedValue> msg = GetThis(argv);                                              \
217         if (!msg->IsDate()) {                                                                     \
218             THROW_TYPE_ERROR_AND_RETURN(thread, "Not a Date Object", JSTaggedValue::Exception()); \
219         }                                                                                         \
220         JSHandle<JSDate> jsDate(thread, JSDate::Cast(msg->GetTaggedObject()));                    \
221         JSTaggedValue result = jsDate->SetDateValue(argv, code, isLocal);                         \
222         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);                                            \
223         jsDate->SetTimeValue(thread, result);                                                     \
224         return result;                                                                            \
225     }
226 
227 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
228 #define DATE_TO_STRING(name)                                                                      \
229     static JSTaggedValue name(EcmaRuntimeCallInfo *argv)                                          \
230     {                                                                                             \
231         ASSERT(argv);                                                                             \
232         JSThread *thread = argv->GetThread();                                                     \
233         JSHandle<JSTaggedValue> msg = GetThis(argv);                                              \
234         if (!msg->IsDate()) {                                                                     \
235             THROW_TYPE_ERROR_AND_RETURN(thread, "Not a Date Object", JSTaggedValue::Exception()); \
236         }                                                                                         \
237         if (std::isnan(JSDate::Cast(msg->GetTaggedObject())->GetTimeValue().GetDouble())) {       \
238             THROW_RANGE_ERROR_AND_RETURN(thread, "range error", JSTaggedValue::Exception());      \
239         }                                                                                         \
240         return JSDate::Cast(msg->GetTaggedObject())->name(thread);                                \
241     }
242 
243 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
244 #define DATE_STRING(name)                                                                                          \
245     static JSTaggedValue name(EcmaRuntimeCallInfo *argv)                                                           \
246     {                                                                                                              \
247         ASSERT(argv);                                                                                              \
248         JSThread *thread = argv->GetThread();                                                                      \
249         JSHandle<JSTaggedValue> msg = GetThis(argv);                                                               \
250         if (!msg->IsDate()) {                                                                                      \
251             THROW_TYPE_ERROR_AND_RETURN(thread, "Not a Date Object", JSTaggedValue::Exception());                  \
252         }                                                                                                          \
253         if (std::isnan(JSDate::Cast(msg->GetTaggedObject())->GetTimeValue().GetDouble())) {                        \
254             return thread->GetEcmaVM()->GetFactory()->NewFromASCII("Invalid Date").GetTaggedValue();               \
255         }                                                                                                          \
256         return JSDate::Cast(msg->GetTaggedObject())->name(thread);                                                 \
257     }
258 
259 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
260 #define GET_DATE_VALUE(name, code, isLocal)                                                       \
261     static JSTaggedValue name(EcmaRuntimeCallInfo *argv)                                          \
262     {                                                                                             \
263         ASSERT(argv);                                                                             \
264         JSThread *thread = argv->GetThread();                                                     \
265         JSHandle<JSTaggedValue> msg = GetThis(argv);                                              \
266         if (!msg->IsDate()) {                                                                     \
267             THROW_TYPE_ERROR_AND_RETURN(thread, "Not a Date Object", JSTaggedValue::Exception()); \
268         }                                                                                         \
269         JSHandle<JSDate> jsDate(thread, JSDate::Cast(msg->GetTaggedObject()));                    \
270         double result = jsDate->GetDateValue(jsDate->GetTimeValue().GetDouble(), code, isLocal);  \
271         return GetTaggedDouble(result);                                                           \
272     }
273 
274 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
275 #define THROW_NEW_ERROR_AND_RETURN(thread, error)       \
276     do {                                                \
277         if (!(thread)->HasPendingException()) {         \
278             (thread)->SetException(error);              \
279             if ((thread)->IsPrintBCOffset()) {          \
280                 (thread)->CollectBCOffsetInfo();        \
281             }                                           \
282         }                                               \
283         return;                                         \
284     } while (false)
285 
286 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
287 #define THROW_ERROR(thread, type, message)                               \
288     do {                                                                 \
289         if ((thread)->HasPendingException()) {                           \
290             return;                                                      \
291         }                                                                \
292         ObjectFactory *_factory = (thread)->GetEcmaVM()->GetFactory();   \
293         JSHandle<JSObject> _error = _factory->GetJSError(type, message); \
294         (thread)->SetException(_error.GetTaggedValue());                 \
295         if ((thread)->IsPrintBCOffset()) {                               \
296             (thread)->CollectBCOffsetInfo();                             \
297         }                                                                \
298         return;                                                          \
299     } while (false)
300 
301 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
302 #define THROW_NEW_ERROR_AND_RETURN_VALUE(thread, error, value) \
303     do {                                                       \
304         if (!(thread)->HasPendingException()) {                \
305             (thread)->SetException(error);                     \
306             if ((thread)->IsPrintBCOffset()) {                 \
307                 (thread)->CollectBCOffsetInfo();               \
308             }                                                  \
309         }                                                      \
310         return (value);                                        \
311     } while (false)
312 
313 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
314 #define THROW_NEW_ERROR_AND_RETURN_HANDLE(thread, errorType, type, message)    \
315     do {                                                                       \
316         if ((thread)->HasPendingException()) {                                 \
317             return JSHandle<type>(thread, JSTaggedValue::Exception());         \
318         }                                                                      \
319         ObjectFactory *_factory = (thread)->GetEcmaVM()->GetFactory();         \
320         JSHandle<JSObject> _error = _factory->GetJSError(errorType, message);  \
321         (thread)->SetException(_error.GetTaggedValue());                       \
322         if ((thread)->IsPrintBCOffset()) {                                     \
323             (thread)->CollectBCOffsetInfo();                                   \
324         }                                                                      \
325         return JSHandle<type>(thread, JSTaggedValue::Exception());             \
326     } while (false)
327 
328 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
329 #define THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, errorType, message, value) \
330     do {                                                                             \
331         if ((thread)->HasPendingException()) {                                       \
332             return (value);                                                          \
333         }                                                                            \
334         ObjectFactory *_factory = (thread)->GetEcmaVM()->GetFactory();               \
335         JSHandle<JSObject> _error = _factory->GetJSError(errorType, message);        \
336         (thread)->SetException(_error.GetTaggedValue());                             \
337         if ((thread)->IsPrintBCOffset()) {                                           \
338             (thread)->CollectBCOffsetInfo();                                         \
339         }                                                                            \
340         return (value);                                                              \
341     } while (false)
342 
343 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
344 #define THROW_TYPE_ERROR_AND_RETURN(thread, message, value)                                      \
345     THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::TYPE_ERROR, message, value)
346 
347 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
348 #define THROW_RANGE_ERROR_AND_RETURN(thread, message, value)                                     \
349     THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::RANGE_ERROR, message, value)
350 
351 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
352 #define THROW_URI_ERROR_AND_RETURN(thread, message, value)                                       \
353     THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::URI_ERROR, message, value)
354 
355 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
356 #define THROW_SYNTAX_ERROR_AND_RETURN(thread, message, value)                                    \
357     THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::SYNTAX_ERROR, message, value)
358 
359 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
360 #define THROW_REFERENCE_ERROR_AND_RETURN(thread, message, value)                                 \
361     THROW_NEW_ERROR_WITH_MSG_AND_RETURN_VALUE(thread, ErrorType::REFERENCE_ERROR, message, value)
362 
363 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
364 #define THROW_TYPE_ERROR(thread, message)               \
365     THROW_ERROR(thread, ErrorType::TYPE_ERROR, message)
366 
367 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
368 #define THROW_OOM_ERROR(thread, message)               \
369     THROW_ERROR(thread, ErrorType::OOM_ERROR, message)
370 
371 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
372 #define RETURN_REJECT_PROMISE_IF_ABRUPT(thread, value, capability)                                 \
373     do {                                                                                           \
374         const GlobalEnvConstants *globalConst = (thread)->GlobalConstants();                       \
375         if ((value).GetTaggedValue().IsCompletionRecord()) {                                       \
376             JSHandle<CompletionRecord> record = JSHandle<CompletionRecord>::Cast(value);           \
377             if (record->IsThrow()) {                                                               \
378                 JSHandle<JSTaggedValue> reject(thread, (capability)->GetReject());                 \
379                 JSHandle<JSTaggedValue> undefine = globalConst->GetHandledUndefined();             \
380                 EcmaRuntimeCallInfo *info =                                                        \
381                     EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefine, undefine, 1);    \
382                 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());             \
383                 info->SetCallArg(record->GetValue());                                              \
384                 JSTaggedValue res = JSFunction::Call(info);                                        \
385                 RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, res);                                    \
386                 return (capability)->GetPromise();                                                 \
387             }                                                                                      \
388         }                                                                                          \
389         if ((thread)->HasPendingException()) {                                                     \
390             (thread)->ClearException();                                                            \
391             JSHandle<JSTaggedValue> reject(thread, (capability)->GetReject());                     \
392             JSHandle<JSTaggedValue> undefined = globalConst->GetHandledUndefined();                \
393             EcmaRuntimeCallInfo *info =                                                            \
394                 EcmaInterpreter::NewRuntimeCallInfo(thread, reject, undefined, undefined, 1);      \
395             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());                 \
396             info->SetCallArg(value.GetTaggedValue());                                              \
397             JSTaggedValue res = JSFunction::Call(info);                                            \
398             RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, res);                                        \
399             return (capability)->GetPromise();                                                     \
400         }                                                                                          \
401     } while (false)
402 
403 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
404 #define RETURN_COMPLETION_IF_ABRUPT(thread, value)                                \
405     do {                                                                          \
406         if ((thread)->HasPendingException()) {                                    \
407             JSHandle<CompletionRecord> completionRecord =                         \
408                 factory->NewCompletionRecord(CompletionRecordType::THROW, value); \
409             return (completionRecord);                                            \
410         }                                                                         \
411     } while (false)
412 
413 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
414 #define DECL_DUMP()                                  \
415     void Dump(std::ostream &os) const DUMP_API_ATTR; \
416     void Dump() const DUMP_API_ATTR                  \
417     {                                                \
418         Dump(std::cout);                             \
419     }                                                \
420     void DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &vec) const;
421 
422 #endif  // defined(__cplusplus)
423 
424 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
425 #define DECL_CAST(TYPE)                           \
426     static TYPE *Cast(TaggedObject *object)       \
427     {                                             \
428         ASSERT(JSTaggedValue(object).Is##TYPE()); \
429         return reinterpret_cast<TYPE *>(object);  \
430     }
431 
432 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
433 #define DECL_VISIT_ARRAY(BEGIN_OFFSET, LENGTH)                                                                       \
434     void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor)                                                       \
435     {                                                                                                                \
436         size_t endOffset = (BEGIN_OFFSET) + (LENGTH) * JSTaggedValue::TaggedTypeSize();                              \
437         visitor(this, ObjectSlot(ToUintPtr(this) + (BEGIN_OFFSET)), ObjectSlot(ToUintPtr(this) + endOffset), false); \
438     }
439 
440 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
441 #define DECL_VISIT_OBJECT(BEGIN_OFFSET, END_OFFSET)                 \
442     void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor)      \
443     {                                                               \
444         visitor(this, ObjectSlot(ToUintPtr(this) + (BEGIN_OFFSET)), \
445                 ObjectSlot(ToUintPtr(this) + (END_OFFSET)), false); \
446     }
447 
448 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
449 #define DECL_VISIT_NATIVE_FIELD(BEGIN_OFFSET, END_OFFSET)                                                              \
450     void VisitRangeSlotForNative(const EcmaObjectRangeVisitor &visitor)                                                \
451     {                                                                                                                  \
452         visitor(this, ObjectSlot(ToUintPtr(this) + (BEGIN_OFFSET)), ObjectSlot(ToUintPtr(this) + (END_OFFSET)), true); \
453     }
454 
455 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
456 #define DECL_VISIT_OBJECT_FOR_JS_OBJECT(PARENTCLASS, BEGIN_OFFSET, END_OFFSET)                               \
457     void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor)                                               \
458     {                                                                                                        \
459         VisitObjects(visitor);                                                                               \
460         /* visit in object fields */                                                                         \
461         auto objSize = this->GetClass()->GetObjectSize();                                                    \
462         if (objSize > SIZE) {                                                                                \
463             visitor(this, ObjectSlot(ToUintPtr(this) + SIZE), ObjectSlot(ToUintPtr(this) + objSize), false); \
464         }                                                                                                    \
465     }                                                                                                        \
466     void VisitObjects(const EcmaObjectRangeVisitor &visitor)                                                 \
467     {                                                                                                        \
468         PARENTCLASS::VisitObjects(visitor);                                                                  \
469         if ((BEGIN_OFFSET) == (END_OFFSET)) {                                                                \
470             return;                                                                                          \
471         }                                                                                                    \
472         visitor(this, ObjectSlot(ToUintPtr(this) + (BEGIN_OFFSET)),                                          \
473                 ObjectSlot(ToUintPtr(this) + (END_OFFSET)), false);                                          \
474     }
475 
476 #if ECMASCRIPT_ENABLE_CAST_CHECK
477     #define CAST_CHECK(CAST_TYPE, CHECK_METHOD)                                                 \
478         static inline CAST_TYPE *Cast(TaggedObject *object)                                     \
479         {                                                                                       \
480             if (!JSTaggedValue(object).CHECK_METHOD()) {                                        \
481                 std::abort();                                                                   \
482             }                                                                                   \
483             return static_cast<CAST_TYPE *>(object);                                            \
484         }                                                                                       \
485         static inline const CAST_TYPE *ConstCast(const TaggedObject *object)                    \
486         {                                                                                       \
487             if (!JSTaggedValue(object).CHECK_METHOD()) {                                        \
488                 std::abort();                                                                   \
489             }                                                                                   \
490             return static_cast<const CAST_TYPE *>(object);                                      \
491         }                                                                                       \
492         static inline CAST_TYPE *Cast(JSTaggedValue value)                                      \
493         {                                                                                       \
494             if (!value.CHECK_METHOD()) {                                                        \
495                 std::abort();                                                                   \
496             }                                                                                   \
497             return static_cast<CAST_TYPE *>(value.GetTaggedObject());                           \
498         }
499 # else
500     #define CAST_CHECK(CAST_TYPE, CHECK_METHOD)                                                   \
501         static inline CAST_TYPE *Cast(TaggedObject *object)                                       \
502         {                                                                                         \
503             ASSERT(JSTaggedValue(object).CHECK_METHOD());                                         \
504             return static_cast<CAST_TYPE *>(object);                                              \
505         }                                                                                         \
506         static const inline CAST_TYPE *ConstCast(const TaggedObject *object)                      \
507         {                                                                                         \
508             ASSERT(JSTaggedValue(object).CHECK_METHOD());                                         \
509             return static_cast<const CAST_TYPE *>(object);                                        \
510         }                                                                                         \
511         static inline CAST_TYPE *Cast(JSTaggedValue value)                                        \
512         {                                                                                         \
513             ASSERT(value.CHECK_METHOD());                                                         \
514             return static_cast<CAST_TYPE *>(value.GetTaggedObject());                             \
515         }
516 
517     #define CAST_NO_CHECK(CAST_TYPE)                                                              \
518         static inline CAST_TYPE *Cast(TaggedObject *object)                                       \
519         {                                                                                         \
520             return static_cast<CAST_TYPE *>(object);                                              \
521         }                                                                                         \
522         static const inline CAST_TYPE *ConstCast(const TaggedObject *object)                      \
523         {                                                                                         \
524             return static_cast<const CAST_TYPE *>(object);                                        \
525         }
526 #endif
527 
528 #define CHECK_OBJECT_SIZE(size)                                                        \
529     if ((size) == 0) {                                                                 \
530         LOG_FULL(FATAL) << __func__ << ":" << __LINE__ << " objectSize is " << (size); \
531     }
532 
533 #define CHECK_REGION_END(begin, end)                                                                  \
534     if ((begin) > (end)) {                                                                            \
535         LOG_FULL(FATAL) << __func__ << ":" << __LINE__ << " begin: " << (begin) << " end: " << (end); \
536     }
537 
538 #define CHECK_JS_THREAD(vm) ASSERT(vm->GetJSThread()->GetThreadId() == JSThread::GetCurrentThreadId())
539 
540 #if !defined(NDEBUG)
541 #define STACK_ASSERT_SCOPE(thread) [[maybe_unused]] StackAssertScope stackAssertScope = StackAssertScope(thread)
542 #else
543 #define STACK_ASSERT_SCOPE(thread) static_cast<void>(0)
544 #endif
545 
546 #if !defined(NDEBUG)
547 #define BUILTINS_ENTRY_DEBUG_LOG() LOG_BUILTINS(DEBUG) << "Builtins C++ " << __func__
548 #else
549 #define BUILTINS_ENTRY_DEBUG_LOG() static_cast<void>(0)
550 #endif
551 
552 #endif  // ECMASCRIPT_ECMA_MACROS_H
553