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#include "ecmascript/ic/ic_compare_op.h"
17
18#include "ecmascript/runtime_call_id.h"
19
20namespace panda::ecmascript {
21JSTaggedValue CompareOp::EqualWithIC(JSThread* thread, JSTaggedValue left,
22    JSTaggedValue right, CompareOpType operationType)
23{
24    INTERPRETER_TRACE(thread, EqualWithIC);
25    double leftDouble = 0;
26    double rightDouble = 0;
27    JSTaggedValue ret = JSTaggedValue::False();
28    switch (operationType) {
29        case CompareOpType::NUMBER_NUMBER: {
30            leftDouble = left.GetNumber();
31            rightDouble = right.GetNumber();
32            ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble));
33            break;
34        }
35        case CompareOpType::STRING_NUMBER: {
36            JSTaggedValue temp = left;
37            left = right;
38            right = temp;
39            [[fallthrough]];
40        }
41        case CompareOpType::NUMBER_STRING: {
42            JSHandle<JSTaggedValue> leftHandle(thread, left);
43            JSHandle<JSTaggedValue> rightHandle(thread, right);
44            rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber();
45            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False());
46            leftDouble = leftHandle.GetTaggedValue().GetNumber();
47            ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble));
48            break;
49        }
50        case CompareOpType::BOOLEAN_NUMBER: {
51            JSTaggedValue temp = left;
52            left = right;
53            right = temp;
54            [[fallthrough]];
55        }
56        case CompareOpType::NUMBER_BOOLEAN: {
57            leftDouble = left.GetNumber();
58            if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) {
59                rightDouble = 1;
60            }
61            ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble));
62            break;
63        }
64        case CompareOpType::OBJ_NUMBER: {
65            JSTaggedValue temp = left;
66            left = right;
67            right = temp;
68            [[fallthrough]];
69        }
70        case CompareOpType::NUMBER_OBJ: {
71            JSHandle<JSTaggedValue> leftHandle(thread, left);
72            JSHandle<JSTaggedValue> rightHandle(thread, right);
73            JSHandle<JSTaggedValue> rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle));
74            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False());
75            if (rightPrimitive->IsNumber()) {
76                ret = EqualWithIC(thread, leftHandle.GetTaggedValue(),
77                                  rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_NUMBER);
78            } else if (rightPrimitive->IsString()) {
79                ret = EqualWithIC(thread, leftHandle.GetTaggedValue(),
80                                  rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING);
81            } else if (rightPrimitive->IsBoolean()) {
82                ret = EqualWithIC(thread, leftHandle.GetTaggedValue(),
83                                  rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN);
84            }
85            break;
86        }
87        case CompareOpType::STRING_STRING: {
88            bool result = EcmaStringAccessor::StringsAreEqual(static_cast<EcmaString *>(left.GetTaggedObject()),
89                static_cast<EcmaString *>(right.GetTaggedObject()));
90            ret = result ? JSTaggedValue::True() : JSTaggedValue::False();
91            break;
92        }
93        case CompareOpType::BOOLEAN_STRING: {
94            JSTaggedValue temp = left;
95            left = right;
96            right = temp;
97            [[fallthrough]];
98        }
99        case CompareOpType::STRING_BOOLEAN: {
100            JSHandle<JSTaggedValue> leftHandle(thread, left);
101            JSHandle<JSTaggedValue> rightHandle(thread, right);
102            leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber();
103            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False());
104            if (rightHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) {
105                rightDouble = 1;
106            }
107            ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble));
108            break;
109        }
110        case CompareOpType::OBJ_STRING: {
111            JSTaggedValue temp = left;
112            left = right;
113            right = temp;
114            [[fallthrough]];
115        }
116        case CompareOpType::STRING_OBJ: {
117            JSHandle<JSTaggedValue> leftHandle(thread, left);
118            JSHandle<JSTaggedValue> rightHandle(thread, right);
119            JSHandle<JSTaggedValue> rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle));
120            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False());
121            if (rightPrimitive->IsNumber()) {
122                ret = EqualWithIC(thread, leftHandle.GetTaggedValue(),
123                                  rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING);
124            } else if (rightPrimitive->IsString()) {
125                ret = EqualWithIC(thread, leftHandle.GetTaggedValue(),
126                                  rightPrimitive.GetTaggedValue(), CompareOpType::STRING_STRING);
127            } else if (rightPrimitive->IsBoolean()) {
128                ret = EqualWithIC(thread, leftHandle.GetTaggedValue(),
129                                  rightPrimitive.GetTaggedValue(), CompareOpType::STRING_BOOLEAN);
130            }
131            break;
132        }
133        case CompareOpType::BOOLEAN_BOOLEAN: {
134            if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) {
135                leftDouble = 1;
136            }
137            if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) {
138                rightDouble = 1;
139            }
140            ret = JSTaggedValue(JSTaggedValue::StrictNumberEquals(leftDouble, rightDouble));
141            break;
142        }
143        case CompareOpType::OBJ_BOOLEAN: {
144            JSHandle<JSTaggedValue> leftHandle(thread, left);
145            JSHandle<JSTaggedValue> rightHandle(thread, right);
146            JSHandle<JSTaggedValue> leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle));
147            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False());
148            if (leftPrimitive->IsNumber()) {
149                ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(),
150                                  rightHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN);
151            } else if (leftPrimitive->IsString()) {
152                ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(),
153                                  rightHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN);
154            } else if (leftPrimitive->IsBoolean()) {
155                ret = EqualWithIC(thread, leftPrimitive.GetTaggedValue(),
156                                  rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN);
157            }
158            break;
159        }
160        case CompareOpType::BOOLEAN_OBJ: {
161            JSHandle<JSTaggedValue> leftHandle(thread, left);
162            JSHandle<JSTaggedValue> rightHandle(thread, right);
163            JSHandle<JSTaggedValue> rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle));
164            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::False());
165            if (rightPrimitive->IsNumber()) {
166                ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(),
167                                  leftHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN);
168            } else if (rightPrimitive->IsString()) {
169                ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(),
170                                  leftHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN);
171            } else if (rightPrimitive->IsBoolean()) {
172                ret = EqualWithIC(thread, rightPrimitive.GetTaggedValue(),
173                                  leftHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN);
174            }
175            break;
176        }
177        case CompareOpType::OBJ_OBJ: {
178            // if same type, must call Type::StrictEqual()
179            JSType xType = left.GetTaggedObject()->GetClass()->GetObjectType();
180            JSType yType = right.GetTaggedObject()->GetClass()->GetObjectType();
181            bool resultObj = false;
182            if (xType == yType) {
183                resultObj = JSTaggedValue::StrictEqual(thread, JSHandle<JSTaggedValue>(thread, left),
184                    JSHandle<JSTaggedValue>(thread, right));
185            }
186            ret = resultObj ? JSTaggedValue::True() : JSTaggedValue::False();
187            break;
188        }
189        case CompareOpType::SYMBOL_SYMBOL: {
190            ret = left == right ? JSTaggedValue::True() : JSTaggedValue::False();
191            break;
192        }
193        case CompareOpType::NULL_NULL:
194        case CompareOpType::NULL_UNDEFINED:
195        case CompareOpType::UNDEFINED_UNDEFINED:
196        case CompareOpType::UNDEFINED_NULL: {
197            ret = JSTaggedValue::True();
198            break;
199        }
200        default:
201            ret = JSTaggedValue::False();
202    }
203    return ret;
204}
205
206JSTaggedValue CompareOp::NotEqualWithIC(JSThread *thread, JSTaggedValue left,
207    JSTaggedValue right, CompareOpType operationType)
208{
209    INTERPRETER_TRACE(thread, NotEqualWithIC);
210    JSTaggedValue res = EqualWithIC(thread, left, right, operationType);
211    return res.IsTrue() ? JSTaggedValue::False() : JSTaggedValue::True();
212}
213
214ComparisonResult CompareOp::Compare(JSThread *thread, JSTaggedValue left,
215    JSTaggedValue right, CompareOpType operationType)
216{
217    INTERPRETER_TRACE(thread, Compare);
218    double leftDouble = 0;
219    double rightDouble = 0;
220    ComparisonResult ret = ComparisonResult::UNDEFINED;
221    switch (operationType) {
222        case CompareOpType::NUMBER_NUMBER: {
223            leftDouble = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
224            rightDouble = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
225            ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble);
226            break;
227        }
228        case CompareOpType::NUMBER_STRING: {
229            JSHandle<JSTaggedValue> leftHandle(thread, left);
230            JSHandle<JSTaggedValue> rightHandle(thread, right);
231
232            rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber();
233            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
234            leftDouble = leftHandle.GetTaggedValue().GetNumber();
235            ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble);
236            break;
237        }
238        case CompareOpType::NUMBER_BOOLEAN: {
239            leftDouble = left.GetNumber();
240            if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) {
241                rightDouble = 1;
242            }
243            ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble);
244            break;
245        }
246        case CompareOpType::NUMBER_OBJ: {
247            JSHandle<JSTaggedValue> leftHandle(thread, left);
248            JSHandle<JSTaggedValue> rightHandle(thread, right);
249            JSHandle<JSTaggedValue> rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle));
250            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
251            if (rightPrimitive->IsNumber()) {
252                ret = Compare(thread, leftHandle.GetTaggedValue(),
253                              rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_NUMBER);
254            } else if (rightPrimitive->IsString()) {
255                ret = Compare(thread, leftHandle.GetTaggedValue(),
256                              rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING);
257            } else if (rightPrimitive->IsBoolean()) {
258                ret = Compare(thread, leftHandle.GetTaggedValue(),
259                              rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN);
260            }
261            break;
262        }
263        case CompareOpType::STRING_STRING: {
264            JSHandle<EcmaString> xHandle(thread, left);
265            JSHandle<EcmaString> yHandle(thread, right);
266            int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle);
267            if (result < 0) {
268                ret = ComparisonResult::LESS;
269            } else if (result == 0) {
270                ret = ComparisonResult::EQUAL;
271            } else {
272                ret = ComparisonResult::GREAT;
273            }
274            break;
275        }
276        case CompareOpType::STRING_NUMBER: {
277            JSHandle<JSTaggedValue> leftHandle(thread, left);
278            JSHandle<JSTaggedValue> rightHandle(thread, right);
279            leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber();
280            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
281            rightDouble = rightHandle.GetTaggedValue().GetNumber();
282            ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble);
283            break;
284        }
285        case CompareOpType::STRING_BOOLEAN: {
286            JSHandle<JSTaggedValue> leftHandle(thread, left);
287            JSHandle<JSTaggedValue> rightHandle(thread, right);
288            leftDouble = JSTaggedValue::ToNumber(thread, leftHandle).GetNumber();
289            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
290            if (rightHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) {
291                rightDouble = 1;
292            }
293            ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble);
294            break;
295        }
296        case CompareOpType::STRING_OBJ: {
297            JSHandle<JSTaggedValue> leftHandle(thread, left);
298            JSHandle<JSTaggedValue> rightHandle(thread, right);
299            JSHandle<JSTaggedValue> rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle));
300            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
301            if (rightPrimitive->IsNumber()) {
302                ret = Compare(thread, leftHandle.GetTaggedValue(),
303                              rightPrimitive.GetTaggedValue(), CompareOpType::NUMBER_STRING);
304            } else if (rightPrimitive->IsString()) {
305                ret = Compare(thread, leftHandle.GetTaggedValue(),
306                              rightPrimitive.GetTaggedValue(), CompareOpType::STRING_STRING);
307            } else if (rightPrimitive->IsBoolean()) {
308                ret = Compare(thread, leftHandle.GetTaggedValue(),
309                              rightPrimitive.GetTaggedValue(), CompareOpType::STRING_BOOLEAN);
310            }
311            break;
312        }
313        case CompareOpType::BOOLEAN_BOOLEAN: {
314            if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) {
315                leftDouble = 1;
316            }
317            if (right.GetRawData() == JSTaggedValue::VALUE_TRUE) {
318                rightDouble = 1;
319            }
320            ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble);
321            break;
322        }
323
324        case CompareOpType::BOOLEAN_NUMBER: {
325            if (left.GetRawData() == JSTaggedValue::VALUE_TRUE) {
326                leftDouble = 1;
327            }
328            rightDouble = right.GetNumber();
329            ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble);
330            break;
331        }
332
333        case CompareOpType::BOOLEAN_STRING: {
334            JSHandle<JSTaggedValue> leftHandle(thread, left);
335            JSHandle<JSTaggedValue> rightHandle(thread, right);
336            rightDouble = JSTaggedValue::ToNumber(thread, rightHandle).GetNumber();
337            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
338            if (leftHandle.GetTaggedValue().GetRawData() == JSTaggedValue::VALUE_TRUE) {
339                leftDouble = 1;
340            }
341            ret = JSTaggedValue::StrictNumberCompare(leftDouble, rightDouble);
342            break;
343        }
344
345        case CompareOpType::BOOLEAN_OBJ: {
346            JSHandle<JSTaggedValue> leftHandle(thread, left);
347            JSHandle<JSTaggedValue> rightHandle(thread, right);
348            JSHandle<JSTaggedValue> rightPrimitive(thread, JSTaggedValue::ToPrimitive(thread, rightHandle));
349            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
350            if (rightPrimitive->IsNumber()) {
351                ret = Compare(thread, rightPrimitive.GetTaggedValue(),
352                              leftHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN);
353            } else if (rightPrimitive->IsString()) {
354                ret = Compare(thread, rightPrimitive.GetTaggedValue(),
355                              leftHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN);
356            } else if (rightPrimitive->IsBoolean()) {
357                ret = Compare(thread, rightPrimitive.GetTaggedValue(),
358                              leftHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN);
359            }
360            break;
361        }
362        case CompareOpType::OBJ_OBJ: {
363            JSHandle<JSTaggedValue> leftHandle(thread, left);
364            JSHandle<JSTaggedValue> rightHandle(thread, right);
365            ret = JSTaggedValue::Compare(thread, leftHandle, rightHandle);
366            break;
367        }
368        case CompareOpType::OBJ_NUMBER: {
369            JSHandle<JSTaggedValue> leftHandle(thread, left);
370            JSHandle<JSTaggedValue> rightHandle(thread, right);
371            JSHandle<JSTaggedValue> leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle));
372            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
373            if (leftPrimitive->IsNumber()) {
374                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
375                              rightHandle.GetTaggedValue(), CompareOpType::NUMBER_NUMBER);
376            } else if (leftPrimitive->IsString()) {
377                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
378                              rightHandle.GetTaggedValue(), CompareOpType::STRING_NUMBER);
379            } else if (leftPrimitive->IsBoolean()) {
380                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
381                              rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_NUMBER);
382            }
383            break;
384        }
385        case CompareOpType::OBJ_STRING: {
386            JSHandle<JSTaggedValue> leftHandle(thread, left);
387            JSHandle<JSTaggedValue> rightHandle(thread, right);
388            JSHandle<JSTaggedValue> leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle));
389            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
390            if (leftPrimitive->IsNumber()) {
391                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
392                              rightHandle.GetTaggedValue(), CompareOpType::NUMBER_STRING);
393            } else if (leftPrimitive->IsString()) {
394                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
395                              rightHandle.GetTaggedValue(), CompareOpType::STRING_STRING);
396            } else if (leftPrimitive->IsBoolean()) {
397                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
398                              rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_STRING);
399            }
400            break;
401        }
402        case CompareOpType::OBJ_BOOLEAN: {
403            JSHandle<JSTaggedValue> leftHandle(thread, left);
404            JSHandle<JSTaggedValue> rightHandle(thread, right);
405            JSHandle<JSTaggedValue> leftPrimitive(thread, JSTaggedValue::ToPrimitive(thread, leftHandle));
406            RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
407            if (leftPrimitive->IsNumber()) {
408                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
409                              rightHandle.GetTaggedValue(), CompareOpType::NUMBER_BOOLEAN);
410            } else if (leftPrimitive->IsString()) {
411                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
412                              rightHandle.GetTaggedValue(), CompareOpType::STRING_BOOLEAN);
413            } else if (leftPrimitive->IsBoolean()) {
414                ret = Compare(thread, leftPrimitive.GetTaggedValue(),
415                              rightHandle.GetTaggedValue(), CompareOpType::BOOLEAN_BOOLEAN);
416            }
417            break;
418        }
419        default:
420            ret = ComparisonResult::UNDEFINED;
421    }
422    return ret;
423}
424
425JSTaggedValue CompareOp::LessWithIC(JSThread *thread, JSTaggedValue left,
426    JSTaggedValue right, CompareOpType operationType)
427{
428    INTERPRETER_TRACE(thread, LessWithIC);
429    bool ret = CompareOp::Compare(thread, left, right, operationType) == ComparisonResult::LESS;
430    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
431    return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
432}
433
434JSTaggedValue CompareOp::LessEqWithIC(JSThread *thread, JSTaggedValue left,
435    JSTaggedValue right, CompareOpType operationType)
436{
437    INTERPRETER_TRACE(thread, LessEqWithIC);
438    bool ret = CompareOp::Compare(thread, left, right, operationType) <= ComparisonResult::EQUAL;
439    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
440    return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
441}
442
443JSTaggedValue CompareOp::GreaterWithIC(JSThread *thread, JSTaggedValue left,
444    JSTaggedValue right, CompareOpType operationType)
445{
446    INTERPRETER_TRACE(thread, GreaterWithIC);
447    bool ret = CompareOp::Compare(thread, left, right, operationType) == ComparisonResult::GREAT;
448    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
449    return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
450}
451
452JSTaggedValue CompareOp::GreaterEqWithIC(JSThread *thread, JSTaggedValue left,
453    JSTaggedValue right, CompareOpType operationType)
454{
455    INTERPRETER_TRACE(thread, GreaterEqWithIC);
456    ComparisonResult comparison = CompareOp::Compare(thread, left, right, operationType);
457    bool ret = (comparison == ComparisonResult::GREAT) || (comparison == ComparisonResult::EQUAL);
458    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
459    return (ret ? JSTaggedValue::True() : JSTaggedValue::False());
460}
461}   // namespace panda::ecmascript
462