1 /*
2 * Copyright (c) 2022 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/compiler/typed_hcr_lowering.h"
17
18 #include "ecmascript/compiler/builtins_lowering.h"
19 #include "ecmascript/compiler/deopt_type.h"
20 #include "ecmascript/compiler/new_object_stub_builder.h"
21 #include "ecmascript/js_map.h"
22 #include "ecmascript/js_primitive_ref.h"
23 #include "ecmascript/linked_hash_table.h"
24
25 namespace panda::ecmascript::kungfu {
VisitGate(GateRef gate)26 GateRef TypedHCRLowering::VisitGate(GateRef gate)
27 {
28 GateRef glue = glue_;
29 auto op = acc_.GetOpCode(gate);
30 [[maybe_unused]] auto scopedGate = circuit_->VisitGateBegin(gate);
31 switch (op) {
32 case OpCode::PRIMITIVE_TYPE_CHECK:
33 LowerPrimitiveTypeCheck(gate);
34 break;
35 case OpCode::BUILTIN_INSTANCE_HCLASS_CHECK:
36 LowerBuiltinInstanceHClassCheck(gate);
37 break;
38 case OpCode::BUILTIN_PROTOTYPE_HCLASS_CHECK:
39 LowerBuiltinPrototypeHClassCheck(gate);
40 break;
41 case OpCode::STABLE_ARRAY_CHECK:
42 LowerStableArrayCheck(glue, gate);
43 break;
44 case OpCode::TYPED_ARRAY_CHECK:
45 LowerTypedArrayCheck(glue, gate);
46 break;
47 case OpCode::ECMA_STRING_CHECK:
48 LowerEcmaStringCheck(gate, glue);
49 break;
50 case OpCode::INTERN_STRING_CHECK:
51 LowerInternStringCheck(gate, glue);
52 break;
53 case OpCode::STRING_KEY_CHECK:
54 LowerStringKeyCheck(gate, glue);
55 break;
56 case OpCode::INTERN_STRING_KEY_CHECK:
57 LowerInternStringKeyCheck(gate, glue);
58 break;
59 case OpCode::ECMA_MAP_CHECK:
60 LowerEcmaMapCheck(glue, gate);
61 break;
62 case OpCode::FLATTEN_TREE_STRING_CHECK:
63 LowerFlattenTreeStringCheck(gate, glue);
64 break;
65 case OpCode::LOAD_STRING_LENGTH:
66 LowerStringLength(gate);
67 break;
68 case OpCode::LOAD_MAP_SIZE:
69 LowerMapSize(gate);
70 break;
71 case OpCode::LOAD_TYPED_ARRAY_LENGTH:
72 LowerLoadTypedArrayLength(gate);
73 break;
74 case OpCode::OBJECT_TYPE_CHECK:
75 LowerObjectTypeCheck(glue, gate);
76 break;
77 case OpCode::RANGE_CHECK_PREDICATE:
78 LowerRangeCheckPredicate(gate);
79 break;
80 case OpCode::INDEX_CHECK:
81 LowerIndexCheck(gate);
82 break;
83 case OpCode::TYPED_CALLTARGETCHECK_OP:
84 LowerJSCallTargetCheck(gate, glue);
85 break;
86 case OpCode::CALL_TARGET_IS_COMPILED_CHECK:
87 LowerCallTargetIsCompiledCheck(gate);
88 break;
89 case OpCode::TYPED_CALL_CHECK:
90 LowerCallTargetCheck(gate);
91 break;
92 case OpCode::JSINLINETARGET_TYPE_CHECK:
93 LowerJSInlineTargetTypeCheck(gate, glue);
94 break;
95 case OpCode::JSINLINETARGET_HEAPCONSTANT_CHECK:
96 LowerJSInlineTargetHeapConstantCheck(gate);
97 break;
98 case OpCode::TYPE_CONVERT:
99 LowerTypeConvert(gate);
100 break;
101 case OpCode::LOAD_PROPERTY:
102 LowerLoadProperty(gate);
103 break;
104 case OpCode::CALL_PRIVATE_GETTER:
105 LowerCallPrivateGetter(gate, glue);
106 break;
107 case OpCode::CALL_PRIVATE_SETTER:
108 LowerCallPrivateSetter(gate, glue);
109 break;
110 case OpCode::CALL_GETTER:
111 LowerCallGetter(gate, glue);
112 break;
113 case OpCode::STORE_PROPERTY:
114 case OpCode::STORE_PROPERTY_NO_BARRIER:
115 LowerStoreProperty(gate);
116 break;
117 case OpCode::CALL_SETTER:
118 LowerCallSetter(gate, glue);
119 break;
120 case OpCode::LOAD_ARRAY_LENGTH:
121 LowerLoadArrayLength(gate);
122 break;
123 case OpCode::LOAD_ELEMENT:
124 LowerLoadElement(gate, glue);
125 break;
126 case OpCode::STORE_ELEMENT:
127 LowerStoreElement(gate, glue);
128 break;
129 case OpCode::TYPED_CALL_BUILTIN:
130 case OpCode::TYPED_CALL_BUILTIN_SIDE_EFFECT:
131 LowerTypedCallBuitin(gate);
132 break;
133 case OpCode::TYPED_NEW_ALLOCATE_THIS:
134 LowerTypedNewAllocateThis(gate, glue);
135 break;
136 case OpCode::TYPED_SUPER_ALLOCATE_THIS:
137 LowerTypedSuperAllocateThis(gate, glue);
138 break;
139 case OpCode::GET_SUPER_CONSTRUCTOR:
140 LowerGetSuperConstructor(glue, gate);
141 break;
142 case OpCode::COW_ARRAY_CHECK:
143 LowerCowArrayCheck(gate, glue);
144 break;
145 case OpCode::LOOK_UP_HOLDER:
146 LowerLookupHolder(glue, gate);
147 break;
148 case OpCode::LOAD_GETTER:
149 LowerLoadGetter(gate, glue);
150 break;
151 case OpCode::LOAD_SETTER:
152 LowerLoadSetter(gate, glue);
153 break;
154 case OpCode::PROTOTYPE_CHECK:
155 LowerPrototypeCheck(glue, gate);
156 break;
157 case OpCode::STRING_EQUAL:
158 LowerStringEqual(gate, glue);
159 break;
160 case OpCode::TYPE_OF_CHECK:
161 LowerTypeOfCheck(gate);
162 break;
163 case OpCode::TYPE_OF:
164 LowerTypeOf(gate, glue);
165 break;
166 case OpCode::TYPED_CONSTRUCTOR_CHECK:
167 LowerTypedConstructorCheck(gate, glue);
168 break;
169 case OpCode::ARRAY_CONSTRUCTOR_CHECK:
170 LowerArrayConstructorCheck(gate, glue);
171 break;
172 case OpCode::ARRAY_CONSTRUCTOR:
173 LowerArrayConstructor(gate, glue);
174 break;
175 case OpCode::FLOAT32_ARRAY_CONSTRUCTOR_CHECK:
176 LowerFloat32ArrayConstructorCheck(gate, glue);
177 break;
178 case OpCode::FLOAT32_ARRAY_CONSTRUCTOR:
179 LowerFloat32ArrayConstructor(gate, glue);
180 break;
181 case OpCode::LOAD_BUILTIN_OBJECT:
182 LowerLoadBuiltinObject(gate);
183 break;
184 case OpCode::OBJECT_CONSTRUCTOR_CHECK:
185 LowerObjectConstructorCheck(gate, glue);
186 break;
187 case OpCode::OBJECT_CONSTRUCTOR:
188 LowerObjectConstructor(gate, glue);
189 break;
190 case OpCode::BOOLEAN_CONSTRUCTOR_CHECK:
191 LowerBooleanConstructorCheck(gate, glue);
192 break;
193 case OpCode::BOOLEAN_CONSTRUCTOR:
194 LowerBooleanConstructor(gate, glue);
195 break;
196 case OpCode::ORDINARY_HAS_INSTANCE:
197 if (compilationEnv_->IsJitCompiler()) {
198 LowerOrdinaryHasInstanceForJIT(gate, glue);
199 } else {
200 LowerOrdinaryHasInstance(gate, glue);
201 }
202 break;
203 case OpCode::PROTO_CHANGE_MARKER_CHECK:
204 LowerProtoChangeMarkerCheck(glue, gate);
205 break;
206 case OpCode::PRIMTYPE_PROTO_CHANGE_MARKER_CHECK:
207 LowerPrimitiveTypeProtoChangeMarkerCheck(glue, gate);
208 break;
209 case OpCode::MONO_CALL_GETTER_ON_PROTO:
210 LowerMonoCallGetterOnProto(gate, glue);
211 break;
212 case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
213 LowerMonoLoadPropertyOnProto(glue, gate);
214 break;
215 case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
216 LowerMonoStorePropertyLookUpProto(gate, glue);
217 break;
218 case OpCode::MONO_STORE_PROPERTY:
219 LowerMonoStoreProperty(gate, glue);
220 break;
221 case OpCode::TYPED_CREATE_OBJ_WITH_BUFFER:
222 LowerTypedCreateObjWithBuffer(gate, glue);
223 break;
224 case OpCode::STRING_FROM_SINGLE_CHAR_CODE:
225 LowerStringFromSingleCharCode(gate, glue);
226 break;
227 case OpCode::MIGRATE_ARRAY_WITH_KIND:
228 LowerMigrateArrayWithKind(gate, glue);
229 break;
230 case OpCode::NUMBER_TO_STRING:
231 LowerNumberToString(gate, glue);
232 break;
233 case OpCode::ECMA_OBJECT_CHECK:
234 LowerEcmaObjectCheck(gate);
235 break;
236 case OpCode::ELEMENTSKIND_CHECK:
237 LowerElementskindCheck(glue, gate);
238 break;
239 case OpCode::INLINE_SUPER_CTOR_CHECK:
240 LowerInlineSuperCtorCheck(glue, gate);
241 break;
242 case OpCode::CHECK_CONSTRUCTOR:
243 LowerCheckConstructor(gate, glue);
244 break;
245 default:
246 break;
247 }
248 return Circuit::NullGate();
249 }
250
LowerJSCallTargetCheck(GateRef gate,GateRef glue)251 void TypedHCRLowering::LowerJSCallTargetCheck(GateRef gate, GateRef glue)
252 {
253 TypedCallTargetCheckOp Op = acc_.GetTypedCallTargetCheckOp(gate);
254 switch (Op) {
255 case TypedCallTargetCheckOp::JSCALL: {
256 LowerJSCallTargetTypeCheck(gate, glue);
257 break;
258 }
259 case TypedCallTargetCheckOp::JSCALL_FAST: {
260 LowerJSFastCallTargetTypeCheck(gate, glue);
261 break;
262 }
263 case TypedCallTargetCheckOp::JSCALLTHIS: {
264 LowerJSCallThisTargetTypeCheck(gate, glue);
265 break;
266 }
267 case TypedCallTargetCheckOp::JSCALLTHIS_FAST: {
268 LowerJSFastCallThisTargetTypeCheck(gate, glue);
269 break;
270 }
271 case TypedCallTargetCheckOp::JSCALLTHIS_NOGC: {
272 LowerJSNoGCCallThisTargetTypeCheck(gate, glue);
273 break;
274 }
275 case TypedCallTargetCheckOp::JSCALLTHIS_FAST_NOGC: {
276 LowerJSNoGCFastCallThisTargetTypeCheck(gate, glue);
277 break;
278 }
279 case TypedCallTargetCheckOp::JS_NEWOBJRANGE: {
280 LowerJSNewObjRangeCallTargetCheck(gate, glue);
281 break;
282 }
283 default:
284 LOG_ECMA(FATAL) << "this branch is unreachable";
285 UNREACHABLE();
286 }
287 }
288
LowerPrimitiveTypeCheck(GateRef gate)289 void TypedHCRLowering::LowerPrimitiveTypeCheck(GateRef gate)
290 {
291 Environment env(gate, circuit_, &builder_);
292 auto type = acc_.GetParamGateType(gate);
293 if (type.IsIntType()) {
294 LowerIntCheck(gate);
295 } else if (type.IsDoubleType()) {
296 LowerDoubleCheck(gate);
297 } else if (type.IsNumberType()) {
298 LowerNumberCheck(gate);
299 } else if (type.IsBooleanType()) {
300 LowerBooleanCheck(gate);
301 } else {
302 LOG_ECMA(FATAL) << "this branch is unreachable";
303 UNREACHABLE();
304 }
305 }
306
LowerIntCheck(GateRef gate)307 void TypedHCRLowering::LowerIntCheck(GateRef gate)
308 {
309 GateRef frameState = GetFrameState(gate);
310
311 GateRef value = acc_.GetValueIn(gate, 0);
312 GateRef typeCheck = builder_.TaggedIsInt(value);
313 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTINT6);
314
315 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
316 }
317
LowerDoubleCheck(GateRef gate)318 void TypedHCRLowering::LowerDoubleCheck(GateRef gate)
319 {
320 GateRef frameState = GetFrameState(gate);
321
322 GateRef value = acc_.GetValueIn(gate, 0);
323 GateRef typeCheck = builder_.TaggedIsDouble(value);
324 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTDOUBLE3);
325
326 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
327 }
328
LowerNumberCheck(GateRef gate)329 void TypedHCRLowering::LowerNumberCheck(GateRef gate)
330 {
331 GateRef frameState = GetFrameState(gate);
332
333 GateRef value = acc_.GetValueIn(gate, 0);
334 GateRef typeCheck = builder_.TaggedIsNumber(value);
335 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTNUMBER2);
336
337 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
338 }
339
LowerBooleanCheck(GateRef gate)340 void TypedHCRLowering::LowerBooleanCheck(GateRef gate)
341 {
342 GateRef frameState = GetFrameState(gate);
343
344 GateRef value = acc_.GetValueIn(gate, 0);
345 GateRef typeCheck = builder_.TaggedIsBoolean(value);
346 builder_.DeoptCheck(typeCheck, frameState, DeoptType::NOTBOOL2);
347
348 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
349 }
350
LowerStableArrayCheck(GateRef glue,GateRef gate)351 void TypedHCRLowering::LowerStableArrayCheck(GateRef glue, GateRef gate)
352 {
353 Environment env(gate, circuit_, &builder_);
354 GateRef frameState = GetFrameState(gate);
355
356 GateRef receiver = acc_.GetValueIn(gate, 0);
357 builder_.HeapObjectCheck(receiver, frameState);
358
359 GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
360 ArrayMetaDataAccessor accessor = acc_.GetArrayMetaDataAccessor(gate);
361 builder_.HClassStableArrayCheck(receiverHClass, frameState, accessor);
362 builder_.ArrayGuardianCheck(frameState);
363
364 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
365 }
366
SetDeoptTypeInfo(JSType jstype,DeoptType & type,size_t & typedArrayRootHclassIndex,size_t & typedArrayRootHclassOnHeapIndex)367 void TypedHCRLowering::SetDeoptTypeInfo(JSType jstype, DeoptType &type, size_t &typedArrayRootHclassIndex,
368 size_t &typedArrayRootHclassOnHeapIndex)
369 {
370 type = DeoptType::NOTARRAY1;
371 switch (jstype) {
372 case JSType::JS_INT8_ARRAY:
373 typedArrayRootHclassIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_INDEX;
374 typedArrayRootHclassOnHeapIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
375 break;
376 case JSType::JS_UINT8_ARRAY:
377 typedArrayRootHclassIndex = GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_INDEX;
378 typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
379 break;
380 case JSType::JS_UINT8_CLAMPED_ARRAY:
381 typedArrayRootHclassIndex = GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_INDEX;
382 typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT8_CLAMPED_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
383 break;
384 case JSType::JS_INT16_ARRAY:
385 typedArrayRootHclassIndex = GlobalEnv::INT16_ARRAY_ROOT_HCLASS_INDEX;
386 typedArrayRootHclassOnHeapIndex = GlobalEnv::INT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
387 break;
388 case JSType::JS_UINT16_ARRAY:
389 typedArrayRootHclassIndex = GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_INDEX;
390 typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT16_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
391 break;
392 case JSType::JS_INT32_ARRAY:
393 typedArrayRootHclassIndex = GlobalEnv::INT32_ARRAY_ROOT_HCLASS_INDEX;
394 typedArrayRootHclassOnHeapIndex = GlobalEnv::INT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
395 break;
396 case JSType::JS_UINT32_ARRAY:
397 typedArrayRootHclassIndex = GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_INDEX;
398 typedArrayRootHclassOnHeapIndex = GlobalEnv::UINT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
399 break;
400 case JSType::JS_FLOAT32_ARRAY:
401 typedArrayRootHclassIndex = GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_INDEX;
402 typedArrayRootHclassOnHeapIndex = GlobalEnv::FLOAT32_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
403 break;
404 case JSType::JS_FLOAT64_ARRAY:
405 typedArrayRootHclassIndex = GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_INDEX;
406 typedArrayRootHclassOnHeapIndex = GlobalEnv::FLOAT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
407 break;
408 case JSType::JS_BIGINT64_ARRAY:
409 typedArrayRootHclassIndex = GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_INDEX;
410 typedArrayRootHclassOnHeapIndex = GlobalEnv::BIGINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
411 break;
412 case JSType::JS_BIGUINT64_ARRAY:
413 typedArrayRootHclassIndex = GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_INDEX;
414 typedArrayRootHclassOnHeapIndex = GlobalEnv::BIGUINT64_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
415 break;
416 default:
417 LOG_ECMA(FATAL) << "this branch is unreachable";
418 UNREACHABLE();
419 }
420 }
421
LowerTypedArrayCheck(GateRef glue,GateRef gate)422 void TypedHCRLowering::LowerTypedArrayCheck(GateRef glue, GateRef gate)
423 {
424 Environment env(gate, circuit_, &builder_);
425 TypedArrayMetaDataAccessor accessor = acc_.GetTypedArrayMetaDataAccessor(gate);
426 size_t typedArrayRootHclassIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_INDEX;
427 size_t typedArrayRootHclassOnHeapIndex = GlobalEnv::INT8_ARRAY_ROOT_HCLASS_ON_HEAP_INDEX;
428 auto deoptType = DeoptType::NONE;
429 ParamType paramType = accessor.GetParamType();
430 ASSERT(paramType.IsBuiltinType());
431 auto builtinType = paramType.GetBuiltinType();
432 SetDeoptTypeInfo(static_cast<JSType>(builtinType), deoptType, typedArrayRootHclassIndex,
433 typedArrayRootHclassOnHeapIndex);
434
435 GateRef frameState = GetFrameState(gate);
436 GateRef globalEnv = circuit_->GetGlobalEnvCache();
437 GateRef receiver = acc_.GetValueIn(gate, 0);
438 builder_.HeapObjectCheck(receiver, frameState);
439 GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
440
441 OnHeapMode onHeapMode = accessor.GetOnHeapMode();
442 if (OnHeap::IsOnHeap(onHeapMode)) {
443 GateRef rootOnHeapHclass = builder_.GetGlobalEnvObj(globalEnv, typedArrayRootHclassOnHeapIndex);
444 GateRef check = builder_.Equal(receiverHClass, rootOnHeapHclass);
445 builder_.DeoptCheck(check, frameState, deoptType);
446 } else if (OnHeap::IsNotOnHeap(onHeapMode)) {
447 GateRef rootHclass = builder_.GetGlobalEnvObj(globalEnv, typedArrayRootHclassIndex);
448 GateRef check = builder_.Equal(receiverHClass, rootHclass);
449 builder_.DeoptCheck(check, frameState, deoptType);
450 } else {
451 GateRef rootHclass = builder_.GetGlobalEnvObj(globalEnv, typedArrayRootHclassIndex);
452 GateRef rootOnHeapHclass = builder_.GetGlobalEnvObj(globalEnv, typedArrayRootHclassOnHeapIndex);
453 GateRef check1 = builder_.Equal(receiverHClass, rootHclass);
454 GateRef check2 = builder_.Equal(receiverHClass, rootOnHeapHclass);
455 builder_.DeoptCheck(builder_.BitOr(check1, check2), frameState, deoptType);
456 }
457 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
458 }
459
LowerInternStringKeyCheck(GateRef gate,GateRef glue)460 void TypedHCRLowering::LowerInternStringKeyCheck(GateRef gate, GateRef glue)
461 {
462 Environment env(gate, circuit_, &builder_);
463 GateRef frameState = GetFrameState(gate);
464 GateRef key = acc_.GetValueIn(gate, 0);
465 GateRef value = acc_.GetValueIn(gate, 1);
466 builder_.HeapObjectCheck(key, frameState);
467 GateRef isString = builder_.TaggedObjectIsString(glue, key, compilationEnv_);
468 builder_.DeoptCheck(isString, frameState, DeoptType::NOTSTRING1);
469 GateRef isInternString = builder_.IsInternString(key);
470 builder_.DeoptCheck(isInternString, frameState, DeoptType::NOTINTERNSTRING1);
471 GateRef isEqual = builder_.Equal(value, key);
472 builder_.DeoptCheck(isEqual, frameState, DeoptType::KEYMISSMATCH);
473 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
474 }
475
LowerStringKeyCheck(GateRef gate,GateRef glue)476 void TypedHCRLowering::LowerStringKeyCheck(GateRef gate, GateRef glue)
477 {
478 Environment env(gate, circuit_, &builder_);
479 GateRef frameState = GetFrameState(gate);
480 GateRef key = acc_.GetValueIn(gate, 0);
481 GateRef value = acc_.GetValueIn(gate, 1);
482 builder_.DeoptCheck(builder_.TaggedIsString(glue, key), frameState, DeoptType::NOTSTRING1);
483 builder_.DeoptCheck(builder_.StringEqual(key, value),
484 frameState, DeoptType::KEYMISSMATCH);
485 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
486 }
487
LowerEcmaStringCheck(GateRef gate,GateRef glue)488 void TypedHCRLowering::LowerEcmaStringCheck(GateRef gate, GateRef glue)
489 {
490 Environment env(gate, circuit_, &builder_);
491 GateRef frameState = GetFrameState(gate);
492 GateRef receiver = acc_.GetValueIn(gate, 0);
493 builder_.HeapObjectCheck(receiver, frameState);
494 GateRef isString = builder_.TaggedObjectIsString(glue, receiver, compilationEnv_);
495 builder_.DeoptCheck(isString, frameState, DeoptType::NOTSTRING1);
496
497 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
498 }
499
LowerInternStringCheck(GateRef gate,GateRef glue)500 void TypedHCRLowering::LowerInternStringCheck(GateRef gate, GateRef glue)
501 {
502 Environment env(gate, circuit_, &builder_);
503 GateRef frameState = GetFrameState(gate);
504 GateRef receiver = acc_.GetValueIn(gate, 0);
505 builder_.HeapObjectCheck(receiver, frameState);
506 GateRef isString = builder_.TaggedObjectIsString(glue, receiver, compilationEnv_);
507 builder_.DeoptCheck(isString, frameState, DeoptType::NOTSTRING1);
508 GateRef isInternString = builder_.IsInternString(receiver);
509 builder_.DeoptCheck(isInternString, frameState, DeoptType::NOTINTERNSTRING1);
510 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
511 }
512
LowerEcmaMapCheck(GateRef glue,GateRef gate)513 void TypedHCRLowering::LowerEcmaMapCheck(GateRef glue, GateRef gate)
514 {
515 Environment env(gate, circuit_, &builder_);
516 GateRef frameState = GetFrameState(gate);
517 GateRef receiver = acc_.GetValueIn(gate, 0);
518 builder_.HeapObjectCheck(receiver, frameState);
519
520 GateRef hclass = builder_.LoadHClassByConstOffset(glue, receiver);
521
522 size_t mapHclassIndex = GlobalEnv::MAP_CLASS_INDEX;
523 GateRef globalEnv = circuit_->GetGlobalEnvCache();
524 GateRef mapHclass = builder_.GetGlobalEnvObj(globalEnv, mapHclassIndex);
525 GateRef isMap = builder_.Equal(hclass, mapHclass, "Check HClass");
526
527 builder_.DeoptCheck(isMap, frameState, DeoptType::ISNOTMAP);
528 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
529 }
530
LowerFlattenTreeStringCheck(GateRef gate,GateRef glue)531 void TypedHCRLowering::LowerFlattenTreeStringCheck(GateRef gate, GateRef glue)
532 {
533 Environment env(gate, circuit_, &builder_);
534 GateRef str = acc_.GetValueIn(gate, 0);
535 DEFVALUE(result, (&builder_), VariableType::JS_POINTER(), str);
536 Label isTreeString(&builder_);
537 Label exit(&builder_);
538
539 BRANCH_CIR(builder_.IsTreeString(glue, str), &isTreeString, &exit);
540 builder_.Bind(&isTreeString);
541 {
542 Label isFlat(&builder_);
543 Label needFlat(&builder_);
544 BRANCH_CIR(builder_.TreeStringIsFlat(glue, str), &isFlat, &needFlat);
545 builder_.Bind(&isFlat);
546 {
547 result = builder_.GetFirstFromTreeString(glue, str);
548 builder_.Jump(&exit);
549 }
550 builder_.Bind(&needFlat);
551 {
552 result = LowerCallRuntime(glue, gate, RTSTUB_ID(SlowFlattenString), { str }, true);
553 builder_.Jump(&exit);
554 }
555 }
556
557 builder_.Bind(&exit);
558 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
559 }
560
GetLengthFromString(GateRef gate)561 GateRef TypedHCRLowering::GetLengthFromString(GateRef gate)
562 {
563 GateRef shiftCount = builder_.Int32(BaseString::LengthBits::START_BIT);
564 return builder_.Int32LSR(
565 builder_.LoadConstOffset(VariableType::INT32(), gate, BaseString::LENGTH_AND_FLAGS_OFFSET), shiftCount);
566 }
567
LowerStringLength(GateRef gate)568 void TypedHCRLowering::LowerStringLength(GateRef gate)
569 {
570 Environment env(gate, circuit_, &builder_);
571 GateRef receiver = acc_.GetValueIn(gate, 0);
572 GateRef length = GetLengthFromString(receiver);
573
574 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), length);
575 }
576
LowerMapSize(GateRef gate)577 void TypedHCRLowering::LowerMapSize(GateRef gate)
578 {
579 Environment env(gate, circuit_, &builder_);
580 GateRef receiver = acc_.GetValueIn(gate, 0);
581
582 GateRef linkedMap = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSMap::LINKED_MAP_OFFSET);
583 GateRef mapSizeTagged = builder_.LoadFromTaggedArray(linkedMap, LinkedHashMap::NUMBER_OF_ELEMENTS_INDEX);
584 GateRef mapSize = builder_.TaggedGetInt(mapSizeTagged);
585
586 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), mapSize);
587 }
588
LowerLoadTypedArrayLength(GateRef gate)589 void TypedHCRLowering::LowerLoadTypedArrayLength(GateRef gate)
590 {
591 Environment env(gate, circuit_, &builder_);
592 GateRef receiver = acc_.GetValueIn(gate, 0);
593 GateRef length = builder_.LoadConstOffset(VariableType::INT32(), receiver, JSTypedArray::ARRAY_LENGTH_OFFSET);
594 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), length);
595 }
596
LowerObjectTypeCheck(GateRef glue,GateRef gate)597 void TypedHCRLowering::LowerObjectTypeCheck(GateRef glue, GateRef gate)
598 {
599 Environment env(gate, circuit_, &builder_);
600 size_t typeCount = acc_.GetNumValueIn(gate) - 1;
601 if (typeCount == 1) {
602 GateRef frameState = GetFrameState(gate);
603 GateRef compare = BuildCompareHClass(glue, gate, frameState);
604 builder_.DeoptCheck(compare, frameState, DeoptType::INCONSISTENTHCLASS6);
605 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
606 return;
607 }
608 LowerSimpleHClassCheck(glue, gate);
609 }
610
BuildCompareHClass(GateRef glue,GateRef gate,GateRef frameState)611 GateRef TypedHCRLowering::BuildCompareHClass(GateRef glue, GateRef gate, GateRef frameState)
612 {
613 GateRef receiver = acc_.GetValueIn(gate, 0);
614 bool isHeapObject = acc_.GetObjectTypeAccessor(gate).IsHeapObject();
615 if (!isHeapObject) {
616 builder_.HeapObjectCheck(receiver, frameState);
617 }
618 GateRef aotHCIndex = acc_.GetValueIn(gate, 1);
619 auto hclassIndex = acc_.GetConstantValue(aotHCIndex);
620 ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
621 GateRef unsharedConstPool = argAcc->GetFrameArgsIn(frameState, FrameArgIdx::UNSHARED_CONST_POOL);
622 GateRef aotHCGate = builder_.LoadHClassFromConstpool(unsharedConstPool, hclassIndex);
623 GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
624 return builder_.Equal(aotHCGate, receiverHClass, "checkHClass");
625 }
626
LowerSimpleHClassCheck(GateRef glue,GateRef gate)627 void TypedHCRLowering::LowerSimpleHClassCheck(GateRef glue, GateRef gate)
628 {
629 GateRef frameState = GetFrameState(gate);
630 GateRef receiver = acc_.GetValueIn(gate, 0);
631 bool isHeapObject = acc_.GetObjectTypeAccessor(gate).IsHeapObject();
632 if (!isHeapObject) {
633 builder_.HeapObjectCheck(receiver, frameState);
634 }
635 DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.Boolean(false));
636 ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
637 GateRef unsharedConstPool = argAcc->GetFrameArgsIn(frameState, FrameArgIdx::UNSHARED_CONST_POOL);
638 GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
639 std::vector<Label> ifFalse;
640 Label resultIsTrue(&builder_);
641 Label resultIsFalse(&builder_);
642 Label exit(&builder_);
643 size_t typeCount = acc_.GetNumValueIn(gate) - 1;
644 ASSERT(typeCount > 0);
645 for (size_t i = 0; i < typeCount - 1; i++) {
646 ifFalse.emplace_back(Label(&builder_));
647 }
648 for (size_t i = 0; i < typeCount; i++) {
649 GateRef aotHCIndex = acc_.GetValueIn(gate, i + 1);
650 auto hclassIndex = acc_.GetConstantValue(aotHCIndex);
651 GateRef aotHCGate = builder_.LoadHClassFromConstpool(unsharedConstPool, hclassIndex);
652
653 if (i != typeCount - 1) {
654 BRANCH_CIR(builder_.Equal(receiverHClass, aotHCGate), &resultIsTrue, &ifFalse[i]);
655 builder_.Bind(&ifFalse[i]);
656 } else {
657 BRANCH_CIR(builder_.Equal(receiverHClass, aotHCGate), &resultIsTrue, &resultIsFalse);
658 }
659 }
660 builder_.Bind(&resultIsFalse);
661 {
662 result = builder_.Boolean(false);
663 builder_.Jump(&exit);
664 }
665 builder_.Bind(&resultIsTrue);
666 {
667 result = builder_.Boolean(true);
668 builder_.Jump(&exit);
669 }
670 builder_.Bind(&exit);
671 auto finalResult = *result;
672 builder_.DeoptCheck(finalResult, frameState, DeoptType::INCONSISTENTHCLASS6);
673 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
674 }
675
LowerRangeCheckPredicate(GateRef gate)676 void TypedHCRLowering::LowerRangeCheckPredicate(GateRef gate)
677 {
678 Environment env(gate, circuit_, &builder_);
679 auto deoptType = DeoptType::NOTARRAY1;
680 GateRef frameState = GetFrameState(gate);
681 GateRef x = acc_.GetValueIn(gate, 0);
682 GateRef y = acc_.GetValueIn(gate, 1);
683 TypedBinaryAccessor accessor = acc_.GetTypedBinaryAccessor(gate);
684 TypedBinOp cond = accessor.GetTypedBinOp();
685 GateRef check = Circuit::NullGate();
686 // check the condition
687 switch (cond) {
688 case TypedBinOp::TYPED_GREATER:
689 check = builder_.Int32GreaterThan(x, y);
690 break;
691 case TypedBinOp::TYPED_GREATEREQ:
692 check = builder_.Int32GreaterThanOrEqual(x, y);
693 break;
694 case TypedBinOp::TYPED_LESS:
695 check = builder_.Int32LessThan(x, y);
696 break;
697 case TypedBinOp::TYPED_LESSEQ:
698 check = builder_.Int32LessThanOrEqual(x, y);
699 break;
700 default:
701 UNREACHABLE();
702 break;
703 }
704 builder_.DeoptCheck(check, frameState, deoptType);
705 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
706 }
707
BuiltinInstanceHClassCheck(Environment * env,GateRef gate)708 void TypedHCRLowering::BuiltinInstanceHClassCheck(Environment *env, GateRef gate)
709 {
710 BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
711 BuiltinTypeId type = accessor.GetBuiltinTypeId();
712 ElementsKind kind = accessor.GetElementsKind();
713 GateRef frameState = GetFrameState(gate);
714 GateRef glue = glue_;
715 GateRef receiver = acc_.GetValueIn(gate, 0);
716 GateRef ihcMatches = Circuit::NullGate();
717 if (type == BuiltinTypeId::ARRAY) {
718 if (Elements::IsGeneric(kind)) {
719 auto index = compilationEnv_->GetArrayHClassIndex(kind, false);
720 auto protoIndex = compilationEnv_->GetArrayHClassIndex(kind, true);
721 GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
722 // If the Elements kind is Generic, hclass comparison is required. Other kinds can ensure that hclass has
723 // not been modified.
724 GateRef globalEnv = circuit_->GetGlobalEnvCache();
725 ihcMatches = LogicOrBuilder(env)
726 .Or(builder_.Equal(receiverHClass,
727 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
728 static_cast<size_t>(index))))
729 .Or(builder_.Equal(receiverHClass,
730 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv,
731 static_cast<size_t>(protoIndex))))
732 .Done();
733 GateRef elementsKind = builder_.GetElementsKindByHClass(receiverHClass);
734 ihcMatches = LogicOrBuilder(env)
735 .Or(ihcMatches)
736 .Or(builder_.NotEqual(elementsKind, builder_.Int32(Elements::ToUint(ElementsKind::GENERIC))))
737 .Done();
738 } else {
739 GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
740 GateRef elementsKind = builder_.GetElementsKindByHClass(receiverHClass);
741 ihcMatches =
742 builder_.NotEqual(elementsKind, builder_.Int32(Elements::ToUint(ElementsKind::GENERIC)));
743 }
744 } else {
745 size_t ihcOffset = JSThread::GlueData::GetBuiltinInstanceHClassOffset(type, env->IsArch32Bit());
746 GateRef initialIhcAddress = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, ihcOffset);
747 GateRef receiverHClass = builder_.LoadHClassByConstOffset(glue, receiver);
748 if (IsTypedArrayType(type)) {
749 // check IHC onHeap hclass
750 size_t ihcOnHeapOffset = JSThread::GlueData::GetBuiltinExtraHClassOffset(type, env->IsArch32Bit());
751 ihcMatches = LogicOrBuilder(env)
752 .Or(builder_.Equal(receiverHClass, initialIhcAddress))
753 .Or(builder_.Equal(receiverHClass,
754 builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, ihcOnHeapOffset)))
755 .Done();
756 } else {
757 ihcMatches = builder_.Equal(receiverHClass, initialIhcAddress);
758 }
759 }
760 // De-opt if HClass of x changed where X is the current builtin object.
761 builder_.DeoptCheck(ihcMatches, frameState, DeoptType::BUILTININSTANCEHCLASSMISMATCH);
762 }
763
BuiltinPrototypeHClassCheck(Environment * env,GateRef gate)764 void TypedHCRLowering::BuiltinPrototypeHClassCheck(Environment *env, GateRef gate)
765 {
766 BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
767 BuiltinTypeId type = accessor.GetBuiltinTypeId();
768 bool isPrototypeOfPrototype = accessor.IsPrototypeOfPrototype();
769 GateRef frameState = GetFrameState(gate);
770 GateRef glue = glue_;
771 GateRef receiver = acc_.GetValueIn(gate, 0);
772 // Only HClasses recorded in the JSThread during builtin initialization are available
773 [[maybe_unused]] JSHClass *initialPrototypeHClass = compilationEnv_->GetBuiltinPrototypeHClass(type);
774 ASSERT(initialPrototypeHClass != nullptr);
775
776 // Phc = PrototypeHClass
777 size_t phcOffset = JSThread::GlueData::GetBuiltinPrototypeHClassOffset(type, env->IsArch32Bit());
778 GateRef receiverPhcAddress = builder_.LoadPrototypeHClass(glue, receiver);
779 GateRef initialPhcAddress = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, phcOffset);
780 GateRef phcMatches = builder_.Equal(receiverPhcAddress, initialPhcAddress);
781 // De-opt if HClass of X.prototype changed where X is the current builtin object.
782 builder_.DeoptCheck(phcMatches, frameState, DeoptType::BUILTINPROTOHCLASSMISMATCH1);
783
784 // array.Iterator should compare PrototypeOfPrototypeHClass.
785 if (isPrototypeOfPrototype) {
786 size_t pphcOffset = JSThread::GlueData::GetBuiltinPrototypeOfPrototypeHClassOffset(type, env->IsArch32Bit());
787 GateRef receiverPPhcAddress = builder_.LoadPrototypeOfPrototypeHClass(glue, receiver);
788 GateRef initialPPhcAddress = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, pphcOffset);
789 GateRef pphcMatches = builder_.Equal(receiverPPhcAddress, initialPPhcAddress);
790 // De-opt if HClass of X.prototype.prototype changed where X is the current builtin object.
791 builder_.DeoptCheck(pphcMatches, frameState, DeoptType::BUILTINPROTOHCLASSMISMATCH2);
792 }
793 }
794
BuiltinInstanceStringTypeCheck(GateRef gate)795 void TypedHCRLowering::BuiltinInstanceStringTypeCheck(GateRef gate)
796 {
797 BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
798 [[maybe_unused]] BuiltinTypeId type = accessor.GetBuiltinTypeId();
799 ASSERT(type == BuiltinTypeId::STRING);
800 GateRef frameState = GetFrameState(gate);
801 GateRef receiver = acc_.GetValueIn(gate, 0);
802 GateRef typeCheck = builder_.TaggedObjectIsString(glue_, receiver, compilationEnv_);
803 builder_.DeoptCheck(typeCheck, frameState, DeoptType::BUILTININSTANCEHCLASSMISMATCH2);
804 }
805
LowerBuiltinInstanceHClassCheck(GateRef gate)806 void TypedHCRLowering::LowerBuiltinInstanceHClassCheck(GateRef gate)
807 {
808 Environment env(gate, circuit_, &builder_);
809 GateRef frameState = GetFrameState(gate);
810 GateRef receiver = acc_.GetValueIn(gate, 0);
811 builder_.HeapObjectCheck(receiver, frameState);
812 BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
813 BuiltinTypeId type = accessor.GetBuiltinTypeId();
814 // BuiltinTypeId::STRING represents primitive string, only need to check the type of hclass here.
815 if (type == BuiltinTypeId::STRING) {
816 BuiltinInstanceStringTypeCheck(gate);
817 } else {
818 BuiltinInstanceHClassCheck(&env, gate); // check IHC
819 }
820 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
821 }
822
LowerBuiltinPrototypeHClassCheck(GateRef gate)823 void TypedHCRLowering::LowerBuiltinPrototypeHClassCheck(GateRef gate)
824 {
825 Environment env(gate, circuit_, &builder_);
826 GateRef frameState = GetFrameState(gate);
827 GateRef receiver = acc_.GetValueIn(gate, 0);
828 builder_.HeapObjectCheck(receiver, frameState);
829 BuiltinPrototypeHClassAccessor accessor = acc_.GetBuiltinHClassAccessor(gate);
830 BuiltinTypeId type = accessor.GetBuiltinTypeId();
831 // BuiltinTypeId::STRING represents primitive string, only need to check the type of hclass here.
832 if (type == BuiltinTypeId::STRING) {
833 BuiltinInstanceStringTypeCheck(gate);
834 } else {
835 BuiltinInstanceHClassCheck(&env, gate); // check IHC
836 BuiltinPrototypeHClassCheck(&env, gate); // check PHC
837 }
838 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
839 }
840
LowerIndexCheck(GateRef gate)841 void TypedHCRLowering::LowerIndexCheck(GateRef gate)
842 {
843 Environment env(gate, circuit_, &builder_);
844 auto deoptType = DeoptType::NOTLEGALIDX1;
845
846 GateRef frameState = GetFrameState(gate);
847 GateRef length = acc_.GetValueIn(gate, 0);
848 GateRef index = acc_.GetValueIn(gate, 1);
849 ASSERT(acc_.GetGateType(length).IsNJSValueType());
850 // UnsignedLessThan can check both lower and upper bounds
851 GateRef lengthCheck = builder_.Int32UnsignedLessThan(index, length);
852 builder_.DeoptCheck(lengthCheck, frameState, deoptType);
853 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), index);
854 }
855
LowerCallRuntime(GateRef glue,GateRef hirGate,int index,const std::vector<GateRef> & args,bool useLabel)856 GateRef TypedHCRLowering::LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
857 bool useLabel)
858 {
859 const std::string name = RuntimeStubCSigns::GetRTName(index);
860 if (useLabel) {
861 GateRef result = builder_.CallRuntime(glue, index, Gate::InvalidGateRef, args, hirGate, name.c_str());
862 return result;
863 } else {
864 const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
865 GateRef target = builder_.IntPtr(index);
866 GateRef result = builder_.Call(cs, glue, target, dependEntry_, args, hirGate, name.c_str());
867 return result;
868 }
869 }
870
LowerTypeConvert(GateRef gate)871 void TypedHCRLowering::LowerTypeConvert(GateRef gate)
872 {
873 Environment env(gate, circuit_, &builder_);
874
875 TypeConvertAccessor accessor(acc_.TryGetValue(gate));
876 ParamType leftType = accessor.GetLeftType();
877 GateType rightType = accessor.GetRightType();
878 if (rightType.IsNumberType()) {
879 GateRef value = acc_.GetValueIn(gate, 0);
880 // NOTICE-PGO: wx support undefined/null/boolean type:
881 if (leftType.HasNumberType()) {
882 LowerPrimitiveToNumber(gate, value, leftType);
883 }
884 return;
885 }
886 }
887
LowerPrimitiveToNumber(GateRef dst,GateRef src,ParamType srcType)888 void TypedHCRLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, ParamType srcType)
889 {
890 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
891 if (srcType.IsBooleanType()) {
892 Label exit(&builder_);
893 Label isTrue(&builder_);
894 Label isFalse(&builder_);
895 BRANCH_CIR(builder_.TaggedIsTrue(src), &isTrue, &isFalse);
896 builder_.Bind(&isTrue);
897 {
898 result = IntToTaggedIntPtr(builder_.Int32(1));
899 builder_.Jump(&exit);
900 }
901 builder_.Bind(&isFalse);
902 {
903 result = IntToTaggedIntPtr(builder_.Int32(0));
904 builder_.Jump(&exit);
905 }
906 builder_.Bind(&exit);
907 } else if (srcType.IsUndefinedType()) {
908 result = DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
909 } else if (srcType.IsBigIntType() || srcType.HasNumberType()) {
910 ASSERT(!srcType.IsIntOverflowType());
911 result = src;
912 } else if (srcType.IsNullType()) {
913 result = IntToTaggedIntPtr(builder_.Int32(0));
914 } else {
915 LOG_ECMA(FATAL) << "this branch is unreachable";
916 UNREACHABLE();
917 }
918 acc_.ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result);
919 }
920
LoadFromConstPool(GateRef glue,GateRef unsharedConstPool,size_t index,size_t valVecType)921 GateRef TypedHCRLowering::LoadFromConstPool(GateRef glue, GateRef unsharedConstPool, size_t index, size_t valVecType)
922 {
923 GateRef constPoolSize = builder_.GetLengthOfTaggedArray(unsharedConstPool);
924 GateRef valVecIndex = builder_.Int32Sub(constPoolSize, builder_.Int32(valVecType));
925 GateRef valVec = builder_.GetValueFromTaggedArray(glue, unsharedConstPool, valVecIndex);
926 return builder_.LoadFromTaggedArray(valVec, index);
927 }
928
LowerLoadProperty(GateRef gate)929 void TypedHCRLowering::LowerLoadProperty(GateRef gate)
930 {
931 Environment env(gate, circuit_, &builder_);
932 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: receiver, plr
933 GateRef receiver = acc_.GetValueIn(gate, 0);
934 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
935 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
936 ASSERT(plr.IsLocal() || plr.IsFunction());
937
938 GateRef result = LoadPropertyFromHolder(receiver, plr);
939
940 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
941 }
942
LowerCallPrivateGetter(GateRef gate,GateRef glue)943 void TypedHCRLowering::LowerCallPrivateGetter(GateRef gate, GateRef glue)
944 {
945 Environment env(gate, circuit_, &builder_);
946 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: receiver, accessor
947 GateRef receiver = acc_.GetValueIn(gate, 0);
948 GateRef accessor = acc_.GetValueIn(gate, 1);
949
950 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
951 result = CallAccessor(glue, gate, accessor, receiver, AccessorMode::GETTER);
952 ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
953 }
954
LowerCallPrivateSetter(GateRef gate,GateRef glue)955 void TypedHCRLowering::LowerCallPrivateSetter(GateRef gate, GateRef glue)
956 {
957 Environment env(gate, circuit_, &builder_);
958 ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: receiver, accessor, value
959 GateRef receiver = acc_.GetValueIn(gate, 0);
960 GateRef accessor = acc_.GetValueIn(gate, 1);
961 GateRef value = acc_.GetValueIn(gate, 2);
962
963 CallAccessor(glue, gate, accessor, receiver, AccessorMode::SETTER, value);
964 ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
965 }
966
LowerCallGetter(GateRef gate,GateRef glue)967 void TypedHCRLowering::LowerCallGetter(GateRef gate, GateRef glue)
968 {
969 Environment env(gate, circuit_, &builder_);
970 ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: receiver, holder, plr
971 GateRef receiver = acc_.GetValueIn(gate, 0);
972 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
973 GateRef holder = acc_.GetValueIn(gate, 2);
974 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
975
976 GateRef accessor = LoadPropertyFromHolder(holder, plr);
977
978 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
979 Label isInternalAccessor(&builder_);
980 Label notInternalAccessor(&builder_);
981 Label callGetter(&builder_);
982 Label exit(&builder_);
983 BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, ¬InternalAccessor);
984 {
985 builder_.Bind(&isInternalAccessor);
986 {
987 result = builder_.CallRuntime(glue, RTSTUB_ID(CallInternalGetter),
988 Gate::InvalidGateRef, { accessor, holder }, gate);
989 builder_.Jump(&exit);
990 }
991 builder_.Bind(¬InternalAccessor);
992 {
993 GateRef getter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::GETTER_OFFSET);
994 BRANCH_CIR(builder_.IsSpecial(getter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callGetter);
995 builder_.Bind(&callGetter);
996 {
997 result = CallAccessor(glue, gate, getter, receiver, AccessorMode::GETTER);
998 builder_.Jump(&exit);
999 }
1000 }
1001 }
1002 builder_.Bind(&exit);
1003 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
1004 }
1005
LowerStoreProperty(GateRef gate)1006 void TypedHCRLowering::LowerStoreProperty(GateRef gate)
1007 {
1008 Environment env(gate, circuit_, &builder_);
1009 ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: receiver, plr, value
1010 GateRef receiver = acc_.GetValueIn(gate, 0);
1011 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1012 GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1013 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1014 ASSERT(plr.IsLocal());
1015 auto op = OpCode(acc_.GetOpCode(gate));
1016 if (op == OpCode::STORE_PROPERTY) {
1017 if (plr.IsInlinedProps()) {
1018 builder_.StoreConstOffset(VariableType::JS_ANY(), receiver, plr.GetOffset(), value);
1019 } else {
1020 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
1021 builder_.SetValueToTaggedArray(
1022 VariableType::JS_ANY(), glue_, properties, builder_.Int32(plr.GetOffset()), value);
1023 }
1024 } else if (op == OpCode::STORE_PROPERTY_NO_BARRIER) {
1025 if (plr.IsInlinedProps()) {
1026 builder_.StoreConstOffset(GetVarType(plr), receiver, plr.GetOffset(), value);
1027 } else {
1028 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
1029 builder_.SetValueToTaggedArray(
1030 GetVarType(plr), glue_, properties, builder_.Int32(plr.GetOffset()), value);
1031 }
1032 } else {
1033 UNREACHABLE();
1034 }
1035 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1036 }
1037
LowerCallSetter(GateRef gate,GateRef glue)1038 void TypedHCRLowering::LowerCallSetter(GateRef gate, GateRef glue)
1039 {
1040 Environment env(gate, circuit_, &builder_);
1041 ASSERT(acc_.GetNumValueIn(gate) == 4); // 4: receiver, holder, plr, value
1042 GateRef receiver = acc_.GetValueIn(gate, 0);
1043 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1044 GateRef holder = acc_.GetValueIn(gate, 2);
1045 GateRef value = acc_.GetValueIn(gate, 3);
1046
1047 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1048 ASSERT(plr.IsAccessor());
1049 GateRef accessor = Circuit::NullGate();
1050 if (plr.IsNotHole()) {
1051 ASSERT(plr.IsLocal());
1052 if (plr.IsInlinedProps()) {
1053 accessor = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
1054 } else {
1055 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
1056 accessor = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
1057 }
1058 } else if (plr.IsLocal()) {
1059 if (plr.IsInlinedProps()) {
1060 accessor = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
1061 } else {
1062 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
1063 accessor = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
1064 }
1065 accessor = builder_.ConvertHoleAsUndefined(accessor);
1066 } else {
1067 UNREACHABLE();
1068 }
1069 Label isInternalAccessor(&builder_);
1070 Label notInternalAccessor(&builder_);
1071 Label callSetter(&builder_);
1072 Label exit(&builder_);
1073 BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, ¬InternalAccessor);
1074 {
1075 builder_.Bind(&isInternalAccessor);
1076 {
1077 builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
1078 Gate::InvalidGateRef, { receiver, accessor, value }, gate);
1079 builder_.Jump(&exit);
1080 }
1081 builder_.Bind(¬InternalAccessor);
1082 {
1083 GateRef setter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
1084 BRANCH_CIR(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
1085 builder_.Bind(&callSetter);
1086 {
1087 CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
1088 builder_.Jump(&exit);
1089 }
1090 }
1091 }
1092 builder_.Bind(&exit);
1093 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1094 }
1095
LowerLoadArrayLength(GateRef gate)1096 void TypedHCRLowering::LowerLoadArrayLength(GateRef gate)
1097 {
1098 Environment env(gate, circuit_, &builder_);
1099 GateRef array = acc_.GetValueIn(gate, 0);
1100 GateRef result = builder_.LoadConstOffset(VariableType::INT32(), array, JSArray::LENGTH_OFFSET);
1101 acc_.SetGateType(gate, GateType::NJSValue());
1102 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1103 }
1104
GetElementSize(BuiltinTypeId id)1105 GateRef TypedHCRLowering::GetElementSize(BuiltinTypeId id)
1106 {
1107 GateRef elementSize = Circuit::NullGate();
1108 switch (id) {
1109 case BuiltinTypeId::INT8_ARRAY:
1110 case BuiltinTypeId::UINT8_ARRAY:
1111 case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
1112 elementSize = builder_.Int32(sizeof(uint8_t));
1113 break;
1114 case BuiltinTypeId::INT16_ARRAY:
1115 case BuiltinTypeId::UINT16_ARRAY:
1116 elementSize = builder_.Int32(sizeof(uint16_t));
1117 break;
1118 case BuiltinTypeId::INT32_ARRAY:
1119 case BuiltinTypeId::UINT32_ARRAY:
1120 case BuiltinTypeId::FLOAT32_ARRAY:
1121 elementSize = builder_.Int32(sizeof(uint32_t));
1122 break;
1123 case BuiltinTypeId::FLOAT64_ARRAY:
1124 elementSize = builder_.Int32(sizeof(double));
1125 break;
1126 default:
1127 LOG_ECMA(FATAL) << "this branch is unreachable";
1128 UNREACHABLE();
1129 }
1130 return elementSize;
1131 }
1132
GetVariableType(BuiltinTypeId id)1133 VariableType TypedHCRLowering::GetVariableType(BuiltinTypeId id)
1134 {
1135 VariableType type = VariableType::JS_ANY();
1136 switch (id) {
1137 case BuiltinTypeId::INT8_ARRAY:
1138 case BuiltinTypeId::UINT8_ARRAY:
1139 case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
1140 type = VariableType::INT8();
1141 break;
1142 case BuiltinTypeId::INT16_ARRAY:
1143 case BuiltinTypeId::UINT16_ARRAY:
1144 type = VariableType::INT16();
1145 break;
1146 case BuiltinTypeId::INT32_ARRAY:
1147 case BuiltinTypeId::UINT32_ARRAY:
1148 type = VariableType::INT32();
1149 break;
1150 case BuiltinTypeId::FLOAT32_ARRAY:
1151 type = VariableType::FLOAT32();
1152 break;
1153 case BuiltinTypeId::FLOAT64_ARRAY:
1154 type = VariableType::FLOAT64();
1155 break;
1156 default:
1157 LOG_ECMA(FATAL) << "this branch is unreachable";
1158 UNREACHABLE();
1159 }
1160 return type;
1161 }
1162
LowerLoadElement(GateRef gate,GateRef glue)1163 void TypedHCRLowering::LowerLoadElement(GateRef gate, GateRef glue)
1164 {
1165 Environment env(gate, circuit_, &builder_);
1166 LoadElementAccessor accessor = acc_.GetLoadElementAccessor(gate);
1167 TypedLoadOp op = accessor.GetTypedLoadOp();
1168 switch (op) {
1169 case TypedLoadOp::ARRAY_LOAD_INT_ELEMENT:
1170 case TypedLoadOp::ARRAY_LOAD_DOUBLE_ELEMENT:
1171 case TypedLoadOp::ARRAY_LOAD_OBJECT_ELEMENT:
1172 case TypedLoadOp::ARRAY_LOAD_TAGGED_ELEMENT:
1173 LowerArrayLoadElement(gate, ArrayState::PACKED, op);
1174 break;
1175 case TypedLoadOp::ARRAY_LOAD_HOLE_TAGGED_ELEMENT:
1176 case TypedLoadOp::ARRAY_LOAD_HOLE_INT_ELEMENT:
1177 case TypedLoadOp::ARRAY_LOAD_HOLE_DOUBLE_ELEMENT:
1178 LowerArrayLoadElement(gate, ArrayState::HOLEY, op);
1179 break;
1180 case TypedLoadOp::INT8ARRAY_LOAD_ELEMENT:
1181 LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT8_ARRAY);
1182 break;
1183 case TypedLoadOp::UINT8ARRAY_LOAD_ELEMENT:
1184 LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT8_ARRAY);
1185 break;
1186 case TypedLoadOp::UINT8CLAMPEDARRAY_LOAD_ELEMENT:
1187 LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT8_CLAMPED_ARRAY);
1188 break;
1189 case TypedLoadOp::INT16ARRAY_LOAD_ELEMENT:
1190 LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT16_ARRAY);
1191 break;
1192 case TypedLoadOp::UINT16ARRAY_LOAD_ELEMENT:
1193 LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT16_ARRAY);
1194 break;
1195 case TypedLoadOp::INT32ARRAY_LOAD_ELEMENT:
1196 LowerTypedArrayLoadElement(gate, BuiltinTypeId::INT32_ARRAY);
1197 break;
1198 case TypedLoadOp::UINT32ARRAY_LOAD_ELEMENT:
1199 LowerTypedArrayLoadElement(gate, BuiltinTypeId::UINT32_ARRAY);
1200 break;
1201 case TypedLoadOp::FLOAT32ARRAY_LOAD_ELEMENT:
1202 LowerTypedArrayLoadElement(gate, BuiltinTypeId::FLOAT32_ARRAY);
1203 break;
1204 case TypedLoadOp::FLOAT64ARRAY_LOAD_ELEMENT:
1205 LowerTypedArrayLoadElement(gate, BuiltinTypeId::FLOAT64_ARRAY);
1206 break;
1207 case TypedLoadOp::STRING_LOAD_ELEMENT:
1208 LowerStringLoadElement(gate, glue);
1209 break;
1210 default:
1211 LOG_ECMA(FATAL) << "this branch is unreachable";
1212 UNREACHABLE();
1213 }
1214 }
1215
LowerCowArrayCheck(GateRef gate,GateRef glue)1216 void TypedHCRLowering::LowerCowArrayCheck(GateRef gate, GateRef glue)
1217 {
1218 Environment env(gate, circuit_, &builder_);
1219 GateRef receiver = acc_.GetValueIn(gate, 0);
1220 Label notCOWArray(&builder_);
1221 Label isCOWArray(&builder_);
1222 GateRef needCOW = builder_.IsJsCOWArray(glue, receiver, compilationEnv_);
1223 BRANCH_CIR(needCOW, &isCOWArray, ¬COWArray);
1224 builder_.Bind(&isCOWArray);
1225 {
1226 LowerCallRuntime(glue, gate, RTSTUB_ID(CheckAndCopyArray), {receiver}, true);
1227 builder_.Jump(¬COWArray);
1228 }
1229 builder_.Bind(¬COWArray);
1230
1231 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1232 }
1233
1234 // for JSArray
LowerArrayLoadElement(GateRef gate,ArrayState arrayState,TypedLoadOp op)1235 void TypedHCRLowering::LowerArrayLoadElement(GateRef gate, ArrayState arrayState, TypedLoadOp op)
1236 {
1237 Environment env(gate, circuit_, &builder_);
1238 GateRef glue = glue_;
1239 GateRef receiver = acc_.GetValueIn(gate, 0);
1240 GateRef index = acc_.GetValueIn(gate, 1);
1241 GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSObject::ELEMENTS_OFFSET);
1242 GateRef result = Circuit::NullGate();
1243 if (arrayState == ArrayState::HOLEY) {
1244 if (op == TypedLoadOp::ARRAY_LOAD_HOLE_INT_ELEMENT ||
1245 op == TypedLoadOp::ARRAY_LOAD_HOLE_DOUBLE_ELEMENT) {
1246 result = builder_.GetValueFromJSArrayWithElementsKind(VariableType::INT64(), element, index);
1247 } else {
1248 result = builder_.GetValueFromTaggedArray(glue, element, index);
1249 result = builder_.ConvertHoleAsUndefined(result);
1250 }
1251 } else {
1252 // When elementsKind swith on, we should get corresponding raw value for Int and Double kind.
1253 result = builder_.GetValueFromTaggedArray(glue, element, index);
1254 }
1255 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1256 }
1257
LowerTypedArrayLoadElement(GateRef gate,BuiltinTypeId id)1258 void TypedHCRLowering::LowerTypedArrayLoadElement(GateRef gate, BuiltinTypeId id)
1259 {
1260 Environment env(gate, circuit_, &builder_);
1261 GateRef glue = glue_;
1262 GateRef receiver = acc_.GetValueIn(gate, 0);
1263 GateRef index = acc_.GetValueIn(gate, 1);
1264 GateRef elementSize = GetElementSize(id);
1265 GateRef offset = builder_.PtrMul(index, elementSize);
1266 VariableType type = GetVariableType(id);
1267
1268 GateRef result = Circuit::NullGate();
1269 LoadElementAccessor accessor = acc_.GetLoadElementAccessor(gate);
1270 OnHeapMode onHeapMode = accessor.GetOnHeapMode();
1271
1272 switch (onHeapMode) {
1273 case OnHeapMode::ON_HEAP: {
1274 result = BuildOnHeapTypedArrayLoadElement(glue, receiver, offset, type);
1275 break;
1276 }
1277 case OnHeapMode::NOT_ON_HEAP: {
1278 result = BuildNotOnHeapTypedArrayLoadElement(glue, receiver, offset, type);
1279 break;
1280 }
1281 default: {
1282 Label isByteArray(&builder_);
1283 Label isArrayBuffer(&builder_);
1284 Label exit(&builder_);
1285 result = BuildTypedArrayLoadElement(glue, receiver, offset, type, &isByteArray, &isArrayBuffer, &exit);
1286 break;
1287 }
1288 }
1289
1290 switch (id) {
1291 case BuiltinTypeId::INT8_ARRAY:
1292 result = builder_.SExtInt8ToInt32(result);
1293 break;
1294 case BuiltinTypeId::UINT8_ARRAY:
1295 case BuiltinTypeId::UINT8_CLAMPED_ARRAY:
1296 result = builder_.ZExtInt8ToInt32(result);
1297 break;
1298 case BuiltinTypeId::INT16_ARRAY:
1299 result = builder_.SExtInt16ToInt32(result);
1300 break;
1301 case BuiltinTypeId::UINT16_ARRAY:
1302 result = builder_.ZExtInt16ToInt32(result);
1303 break;
1304 case BuiltinTypeId::FLOAT32_ARRAY:
1305 result = builder_.FloatArrayElementConvert(result, true);
1306 break;
1307 case BuiltinTypeId::FLOAT64_ARRAY:
1308 result = builder_.FloatArrayElementConvert(result, false);
1309 break;
1310 default:
1311 break;
1312 }
1313 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1314 }
1315
BuildOnHeapTypedArrayLoadElement(GateRef glue,GateRef receiver,GateRef offset,VariableType type)1316 GateRef TypedHCRLowering::BuildOnHeapTypedArrayLoadElement(GateRef glue, GateRef receiver, GateRef offset,
1317 VariableType type)
1318 {
1319 GateRef byteArray =
1320 builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1321 GateRef data = builder_.PtrAdd(byteArray, builder_.IntPtr(ByteArray::DATA_OFFSET));
1322 GateRef result = builder_.Load(type, glue, data, offset);
1323 return result;
1324 }
1325
BuildNotOnHeapTypedArrayLoadElement(GateRef glue,GateRef receiver,GateRef offset,VariableType type)1326 GateRef TypedHCRLowering::BuildNotOnHeapTypedArrayLoadElement(GateRef glue, GateRef receiver, GateRef offset,
1327 VariableType type)
1328 {
1329 GateRef arrayBuffer =
1330 builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1331
1332 GateRef data =
1333 builder_.Load(VariableType::JS_POINTER(), glue, arrayBuffer, builder_.IntPtr(JSArrayBuffer::DATA_OFFSET));
1334 GateRef block =
1335 builder_.Load(VariableType::JS_ANY(), glue, data, builder_.IntPtr(JSNativePointer::POINTER_OFFSET));
1336 GateRef byteOffset = builder_.LoadWithoutBarrier(VariableType::INT32(), receiver,
1337 builder_.IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1338 GateRef result = builder_.Load(type, glue, block, builder_.PtrAdd(offset, byteOffset));
1339 return result;
1340 }
1341
BuildTypedArrayLoadElement(GateRef glue,GateRef receiver,GateRef offset,VariableType type,Label * isByteArray,Label * isArrayBuffer,Label * exit)1342 GateRef TypedHCRLowering::BuildTypedArrayLoadElement(GateRef glue, GateRef receiver, GateRef offset, VariableType type,
1343 Label *isByteArray, Label *isArrayBuffer, Label *exit)
1344 {
1345 GateRef byteArrayOrArrayBuffer =
1346 builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1347 DEFVALUE(data, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1348 DEFVALUE(result, (&builder_), type, builder_.Double(0));
1349
1350 GateRef isOnHeap = builder_.IsOnHeap(builder_.LoadHClassByConstOffset(glue, receiver));
1351 BRANCH_CIR(isOnHeap, isByteArray, isArrayBuffer);
1352 builder_.Bind(isByteArray);
1353 {
1354 data = builder_.PtrAdd(byteArrayOrArrayBuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
1355 result = builder_.Load(type, glue, *data, offset);
1356 builder_.Jump(exit);
1357 }
1358 builder_.Bind(isArrayBuffer);
1359 {
1360 data = builder_.Load(VariableType::JS_POINTER(), glue, byteArrayOrArrayBuffer,
1361 builder_.IntPtr(JSArrayBuffer::DATA_OFFSET));
1362 GateRef block =
1363 builder_.Load(VariableType::JS_ANY(), glue, *data, builder_.IntPtr(JSNativePointer::POINTER_OFFSET));
1364 GateRef byteOffset =
1365 builder_.LoadWithoutBarrier(VariableType::INT32(), receiver,
1366 builder_.IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1367 result = builder_.Load(type, glue, block, builder_.PtrAdd(offset, byteOffset));
1368 builder_.Jump(exit);
1369 }
1370 builder_.Bind(exit);
1371
1372 return *result;
1373 }
1374
LowerStringLoadElement(GateRef gate,GateRef glue)1375 void TypedHCRLowering::LowerStringLoadElement(GateRef gate, GateRef glue)
1376 {
1377 Environment env(gate, circuit_, &builder_);
1378 GateRef receiver = acc_.GetValueIn(gate, 0);
1379 GateRef index = acc_.GetValueIn(gate, 1);
1380 GateRef result = Circuit::NullGate();
1381 if (compilationEnv_->IsJitCompiler()) {
1382 result = builder_.CallStub(glue, gate, CommonStubCSigns::StringLoadElement,
1383 {glue, receiver, index, circuit_->GetGlobalEnvCache()}, "StringLoadElement stub");
1384 } else {
1385 BuiltinsStringStubBuilder builder(&env, circuit_->GetGlobalEnvCache());
1386 result = builder.GetSingleCharCodeByIndex(glue, receiver, index);
1387 }
1388
1389 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
1390 }
1391
LowerStoreElement(GateRef gate,GateRef glue)1392 void TypedHCRLowering::LowerStoreElement(GateRef gate, GateRef glue)
1393 {
1394 Environment env(gate, circuit_, &builder_);
1395 StoreElementAccessor accessor = acc_.GetStoreElementAccessor(gate);
1396 TypedStoreOp op = accessor.GetTypedStoreOp();
1397 switch (op) {
1398 case TypedStoreOp::ARRAY_STORE_ELEMENT:
1399 case TypedStoreOp::ARRAY_STORE_INT_ELEMENT:
1400 case TypedStoreOp::ARRAY_STORE_DOUBLE_ELEMENT:
1401 LowerArrayStoreElement(gate, glue, op);
1402 break;
1403 case TypedStoreOp::INT8ARRAY_STORE_ELEMENT:
1404 LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT8_ARRAY);
1405 break;
1406 case TypedStoreOp::UINT8ARRAY_STORE_ELEMENT:
1407 LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT8_ARRAY);
1408 break;
1409 case TypedStoreOp::UINT8CLAMPEDARRAY_STORE_ELEMENT:
1410 LowerUInt8ClampedArrayStoreElement(gate);
1411 break;
1412 case TypedStoreOp::INT16ARRAY_STORE_ELEMENT:
1413 LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT16_ARRAY);
1414 break;
1415 case TypedStoreOp::UINT16ARRAY_STORE_ELEMENT:
1416 LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT16_ARRAY);
1417 break;
1418 case TypedStoreOp::INT32ARRAY_STORE_ELEMENT:
1419 LowerTypedArrayStoreElement(gate, BuiltinTypeId::INT32_ARRAY);
1420 break;
1421 case TypedStoreOp::UINT32ARRAY_STORE_ELEMENT:
1422 LowerTypedArrayStoreElement(gate, BuiltinTypeId::UINT32_ARRAY);
1423 break;
1424 case TypedStoreOp::FLOAT32ARRAY_STORE_ELEMENT:
1425 LowerTypedArrayStoreElement(gate, BuiltinTypeId::FLOAT32_ARRAY);
1426 break;
1427 case TypedStoreOp::FLOAT64ARRAY_STORE_ELEMENT:
1428 LowerTypedArrayStoreElement(gate, BuiltinTypeId::FLOAT64_ARRAY);
1429 break;
1430 default:
1431 LOG_ECMA(FATAL) << "this branch is unreachable";
1432 UNREACHABLE();
1433 }
1434 }
1435
1436 // for JSArray
LowerArrayStoreElement(GateRef gate,GateRef glue,TypedStoreOp op)1437 void TypedHCRLowering::LowerArrayStoreElement(GateRef gate, GateRef glue, TypedStoreOp op)
1438 {
1439 Environment env(gate, circuit_, &builder_);
1440 GateRef receiver = acc_.GetValueIn(gate, 0); // 0: receiver
1441 GateRef index = acc_.GetValueIn(gate, 1); // 1: index
1442 GateRef value = acc_.GetValueIn(gate, 2); // 2: value
1443
1444 GateRef element = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, JSObject::ELEMENTS_OFFSET);
1445 // Because at retype stage, we have set output according to op
1446 // there is not need to consider about the convertion here.
1447 if (op == TypedStoreOp::ARRAY_STORE_INT_ELEMENT) {
1448 GateRef convertedValue = builder_.ZExtInt32ToInt64(value);
1449 builder_.SetValueToTaggedArray(VariableType::INT64(), glue, element, index, convertedValue);
1450 } else if (op == TypedStoreOp::ARRAY_STORE_DOUBLE_ELEMENT) {
1451 builder_.SetValueToTaggedArray(VariableType::FLOAT64(), glue, element, index, value);
1452 } else {
1453 builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue, element, index, value);
1454 }
1455
1456 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1457 }
1458
1459 // for JSTypedArray
LowerTypedArrayStoreElement(GateRef gate,BuiltinTypeId id)1460 void TypedHCRLowering::LowerTypedArrayStoreElement(GateRef gate, BuiltinTypeId id)
1461 {
1462 Environment env(gate, circuit_, &builder_);
1463 GateRef glue = glue_;
1464 GateRef receiver = acc_.GetValueIn(gate, 0);
1465 GateRef index = acc_.GetValueIn(gate, 1);
1466 GateRef value = acc_.GetValueIn(gate, 2);
1467
1468 GateRef elementSize = GetElementSize(id);
1469 GateRef offset = builder_.PtrMul(index, elementSize);
1470 switch (id) {
1471 case BuiltinTypeId::INT8_ARRAY:
1472 case BuiltinTypeId::UINT8_ARRAY:
1473 value = builder_.TruncInt32ToInt8(value);
1474 break;
1475 case BuiltinTypeId::INT16_ARRAY:
1476 case BuiltinTypeId::UINT16_ARRAY:
1477 value = builder_.TruncInt32ToInt16(value);
1478 break;
1479 case BuiltinTypeId::FLOAT32_ARRAY:
1480 value = builder_.TruncDoubleToFloat32(value);
1481 break;
1482 default:
1483 break;
1484 }
1485
1486 Label isByteArray(&builder_);
1487 Label isArrayBuffer(&builder_);
1488 Label exit(&builder_);
1489 OptStoreElementByOnHeapMode(gate, glue, receiver, offset, value, &isByteArray, &isArrayBuffer, &exit);
1490 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1491 }
1492
OptStoreElementByOnHeapMode(GateRef gate,GateRef glue,GateRef receiver,GateRef offset,GateRef value,Label * isByteArray,Label * isArrayBuffer,Label * exit)1493 void TypedHCRLowering::OptStoreElementByOnHeapMode(GateRef gate, GateRef glue, GateRef receiver, GateRef offset,
1494 GateRef value, Label *isByteArray, Label *isArrayBuffer, Label *exit)
1495 {
1496 StoreElementAccessor accessor = acc_.GetStoreElementAccessor(gate);
1497 OnHeapMode onHeapMode = accessor.GetOnHeapMode();
1498 switch (onHeapMode) {
1499 case OnHeapMode::ON_HEAP: {
1500 BuildOnHeapTypedArrayStoreElement(receiver, offset, value);
1501 break;
1502 }
1503 case OnHeapMode::NOT_ON_HEAP: {
1504 BuildNotOnHeapTypedArrayStoreElement(glue, receiver, offset, value);
1505 break;
1506 }
1507 default: {
1508 BuildTypedArrayStoreElement(glue, receiver, offset, value, isByteArray, isArrayBuffer, exit);
1509 break;
1510 }
1511 }
1512 }
1513
BuildOnHeapTypedArrayStoreElement(GateRef receiver,GateRef offset,GateRef value)1514 void TypedHCRLowering::BuildOnHeapTypedArrayStoreElement(GateRef receiver, GateRef offset, GateRef value)
1515 {
1516 GateRef byteArray = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
1517 JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1518 GateRef data = builder_.PtrAdd(byteArray, builder_.IntPtr(ByteArray::DATA_OFFSET));
1519
1520 builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), data, offset, value);
1521 }
1522
BuildNotOnHeapTypedArrayStoreElement(GateRef glue,GateRef receiver,GateRef offset,GateRef value)1523 void TypedHCRLowering::BuildNotOnHeapTypedArrayStoreElement(GateRef glue, GateRef receiver,
1524 GateRef offset, GateRef value)
1525 {
1526 GateRef arrayBuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
1527 JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1528 GateRef data =
1529 builder_.Load(VariableType::JS_POINTER(), glue, arrayBuffer, builder_.IntPtr(JSArrayBuffer::DATA_OFFSET));
1530 GateRef block = builder_.Load(VariableType::JS_ANY(), glue, data,
1531 builder_.IntPtr(JSNativePointer::POINTER_OFFSET));
1532 GateRef byteOffset =
1533 builder_.LoadWithoutBarrier(VariableType::INT32(), receiver,
1534 builder_.IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1535 builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), block,
1536 builder_.PtrAdd(offset, byteOffset), value);
1537 }
1538
BuildTypedArrayStoreElement(GateRef glue,GateRef receiver,GateRef offset,GateRef value,Label * isByteArray,Label * isArrayBuffer,Label * exit)1539 void TypedHCRLowering::BuildTypedArrayStoreElement(GateRef glue, GateRef receiver, GateRef offset, GateRef value,
1540 Label *isByteArray, Label *isArrayBuffer, Label *exit)
1541 {
1542 GateRef byteArrayOrArrayBuffer = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver,
1543 JSTypedArray::VIEWED_ARRAY_BUFFER_OFFSET);
1544 GateRef isOnHeap = builder_.IsOnHeap(builder_.LoadHClassByConstOffset(glue, receiver));
1545 DEFVALUE(data, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1546 BRANCH_CIR(isOnHeap, isByteArray, isArrayBuffer);
1547 builder_.Bind(isByteArray);
1548 {
1549 data = builder_.PtrAdd(byteArrayOrArrayBuffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
1550 builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), *data, offset, value);
1551 builder_.Jump(exit);
1552 }
1553 builder_.Bind(isArrayBuffer);
1554 {
1555 data = builder_.Load(VariableType::JS_POINTER(), glue, byteArrayOrArrayBuffer,
1556 builder_.IntPtr(JSArrayBuffer::DATA_OFFSET));
1557 GateRef block =
1558 builder_.Load(VariableType::JS_ANY(), glue, *data, builder_.IntPtr(JSNativePointer::POINTER_OFFSET));
1559 GateRef byteOffset =
1560 builder_.LoadWithoutBarrier(VariableType::INT32(), receiver,
1561 builder_.IntPtr(JSTypedArray::BYTE_OFFSET_OFFSET));
1562 builder_.StoreMemory(MemoryType::ELEMENT_TYPE, VariableType::VOID(), block,
1563 builder_.PtrAdd(offset, byteOffset), value);
1564 builder_.Jump(exit);
1565 }
1566 builder_.Bind(exit);
1567 }
1568
1569 // for UInt8ClampedArray
LowerUInt8ClampedArrayStoreElement(GateRef gate)1570 void TypedHCRLowering::LowerUInt8ClampedArrayStoreElement(GateRef gate)
1571 {
1572 Environment env(gate, circuit_, &builder_);
1573
1574 GateRef glue = glue_;
1575 GateRef receiver = acc_.GetValueIn(gate, 0);
1576 GateRef index = acc_.GetValueIn(gate, 1);
1577 GateRef elementSize = builder_.Int32(sizeof(uint8_t));
1578 GateRef offset = builder_.PtrMul(index, elementSize);
1579 GateRef value = acc_.GetValueIn(gate, 2);
1580
1581 DEFVALUE(result, (&builder_), VariableType::INT32(), value);
1582 GateRef topValue = builder_.Int32(static_cast<uint32_t>(UINT8_MAX));
1583 GateRef bottomValue = builder_.Int32(static_cast<uint32_t>(0));
1584 Label isOverFlow(&builder_);
1585 Label notOverFlow(&builder_);
1586 Label exit(&builder_);
1587 Label isByteArray(&builder_);
1588 Label isArrayBuffer(&builder_);
1589 Label quit(&builder_);
1590 BRANCH_CIR(builder_.Int32GreaterThan(value, topValue), &isOverFlow, ¬OverFlow);
1591 builder_.Bind(&isOverFlow);
1592 {
1593 result = topValue;
1594 builder_.Jump(&exit);
1595 }
1596 builder_.Bind(¬OverFlow);
1597 {
1598 Label isUnderSpill(&builder_);
1599 BRANCH_CIR(builder_.Int32LessThan(value, bottomValue), &isUnderSpill, &exit);
1600 builder_.Bind(&isUnderSpill);
1601 {
1602 result = bottomValue;
1603 builder_.Jump(&exit);
1604 }
1605 }
1606 builder_.Bind(&exit);
1607 value = builder_.TruncInt32ToInt8(*result);
1608 OptStoreElementByOnHeapMode(gate, glue, receiver, offset, value, &isByteArray, &isArrayBuffer, &quit);
1609 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1610 }
1611
DoubleToTaggedDoublePtr(GateRef gate)1612 GateRef TypedHCRLowering::DoubleToTaggedDoublePtr(GateRef gate)
1613 {
1614 return builder_.DoubleToTaggedDoublePtr(gate);
1615 }
1616
ChangeInt32ToFloat64(GateRef gate)1617 GateRef TypedHCRLowering::ChangeInt32ToFloat64(GateRef gate)
1618 {
1619 return builder_.ChangeInt32ToFloat64(gate);
1620 }
1621
TruncDoubleToInt(GateRef gate)1622 GateRef TypedHCRLowering::TruncDoubleToInt(GateRef gate)
1623 {
1624 return builder_.TruncInt64ToInt32(builder_.TruncFloatToInt64(gate));
1625 }
1626
IntToTaggedIntPtr(GateRef x)1627 GateRef TypedHCRLowering::IntToTaggedIntPtr(GateRef x)
1628 {
1629 GateRef val = builder_.SExtInt32ToInt64(x);
1630 return builder_.ToTaggedIntPtr(val);
1631 }
1632
LowerTypedCallBuitin(GateRef gate)1633 void TypedHCRLowering::LowerTypedCallBuitin(GateRef gate)
1634 {
1635 BuiltinLowering lowering(circuit_, builder_.GetCompilationConfig(), traceBuiltins_);
1636 lowering.LowerTypedCallBuitin(gate);
1637 }
1638
CallTargetIsCompiledCheck(GateRef func,GateRef frameState,Label * checkAlreadyDeopt,Label * exit)1639 void TypedHCRLowering::CallTargetIsCompiledCheck(GateRef func, GateRef frameState,
1640 Label *checkAlreadyDeopt, Label *exit)
1641 {
1642 GateRef isCompiled = builder_.JudgeAotAndFastCall(func, CircuitBuilder::JudgeMethodType::HAS_AOT);
1643 BRANCH_CIR_LIKELY(isCompiled, exit, checkAlreadyDeopt);
1644 builder_.Bind(checkAlreadyDeopt);
1645 {
1646 GateRef glue = glue_;
1647 GateRef method = builder_.GetMethodFromFunction(glue, func);
1648 GateRef hasDeopt = builder_.AlreadyDeopt(method);
1649 builder_.DeoptCheck(hasDeopt, frameState, DeoptType::CALLTARGETNOTCOMPILED);
1650 builder_.Jump(exit);
1651 }
1652 builder_.Bind(exit);
1653 }
1654
LowerCallTargetIsCompiledCheck(GateRef gate)1655 void TypedHCRLowering::LowerCallTargetIsCompiledCheck(GateRef gate)
1656 {
1657 Environment env(gate, circuit_, &builder_);
1658 Label checkAlreadyDeopt(&builder_);
1659 Label exit(&builder_);
1660 GateRef func = acc_.GetValueIn(gate, 0);
1661 GateRef frameState = acc_.GetFrameState(gate);
1662 builder_.IsCallableCheck(func, frameState);
1663 CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1664 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1665 }
1666
LowerJSCallTargetTypeCheck(GateRef gate,GateRef glue)1667 void TypedHCRLowering::LowerJSCallTargetTypeCheck(GateRef gate, GateRef glue)
1668 {
1669 Environment env(gate, circuit_, &builder_);
1670 Label checkAlreadyDeopt(&builder_);
1671 Label exit(&builder_);
1672 ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
1673 GateRef frameState = GetFrameState(gate);
1674 GateRef sharedConstPool = argAcc->GetFrameArgsIn(frameState, FrameArgIdx::SHARED_CONST_POOL);
1675 auto func = acc_.GetValueIn(gate, 0);
1676 auto methodIndex = acc_.GetValueIn(gate, 1);
1677 builder_.IsCallableCheck(func, frameState);
1678 CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1679
1680 GateRef funcMethodTarget = builder_.GetMethodFromFunction(glue, func);
1681 GateRef methodTarget = builder_.GetValueFromTaggedArray(glue, sharedConstPool, methodIndex);
1682 GateRef check = builder_.Equal(funcMethodTarget, methodTarget);
1683 builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT2);
1684 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1685 }
1686
LowerJSFastCallTargetTypeCheck(GateRef gate,GateRef glue)1687 void TypedHCRLowering::LowerJSFastCallTargetTypeCheck(GateRef gate, GateRef glue)
1688 {
1689 Environment env(gate, circuit_, &builder_);
1690 Label checkAlreadyDeopt(&builder_);
1691 Label exit(&builder_);
1692 ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
1693 GateRef frameState = GetFrameState(gate);
1694 GateRef sharedConstPool = argAcc->GetFrameArgsIn(frameState, FrameArgIdx::SHARED_CONST_POOL);
1695 auto func = acc_.GetValueIn(gate, 0);
1696 auto methodIndex = acc_.GetValueIn(gate, 1);
1697 builder_.IsCallableCheck(func, frameState);
1698 CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1699
1700 GateRef funcMethodTarget = builder_.GetMethodFromFunction(glue, func);
1701 GateRef methodTarget = builder_.GetValueFromTaggedArray(glue, sharedConstPool, methodIndex);
1702 GateRef check = builder_.Equal(funcMethodTarget, methodTarget);
1703 builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT1);
1704 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1705 }
1706
LowerJSCallThisTargetTypeCheck(GateRef gate,GateRef glue)1707 void TypedHCRLowering::LowerJSCallThisTargetTypeCheck(GateRef gate, GateRef glue)
1708 {
1709 Environment env(gate, circuit_, &builder_);
1710 Label checkAlreadyDeopt(&builder_);
1711 Label exit(&builder_);
1712 GateRef frameState = GetFrameState(gate);
1713 auto func = acc_.GetValueIn(gate, 0);
1714 builder_.IsCallableCheck(func, frameState);
1715 CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1716
1717 GateRef methodId = builder_.GetMethodId(glue, func);
1718 GateRef check = builder_.Equal(methodId, acc_.GetValueIn(gate, 1));
1719 builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT3);
1720 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1721 }
1722
LowerJSNoGCCallThisTargetTypeCheck(GateRef gate,GateRef glue)1723 void TypedHCRLowering::LowerJSNoGCCallThisTargetTypeCheck(GateRef gate, GateRef glue)
1724 {
1725 Environment env(gate, circuit_, &builder_);
1726 Label checkAlreadyDeopt(&builder_);
1727 Label exit(&builder_);
1728 GateRef frameState = GetFrameState(gate);
1729 auto func = acc_.GetValueIn(gate, 0);
1730 builder_.IsCallableCheck(func, frameState);
1731 CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1732
1733 GateRef methodId = builder_.GetMethodId(glue, func);
1734 GateRef check = builder_.Equal(methodId, acc_.GetValueIn(gate, 1));
1735 builder_.DeoptCheck(check, frameState, DeoptType::NOTJSCALLTGT4);
1736 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1737 }
1738
LowerJSFastCallThisTargetTypeCheck(GateRef gate,GateRef glue)1739 void TypedHCRLowering::LowerJSFastCallThisTargetTypeCheck(GateRef gate, GateRef glue)
1740 {
1741 Environment env(gate, circuit_, &builder_);
1742 Label checkAlreadyDeopt(&builder_);
1743 Label exit(&builder_);
1744 GateRef frameState = GetFrameState(gate);
1745 auto func = acc_.GetValueIn(gate, 0);
1746 builder_.IsCallableCheck(func, frameState);
1747 CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1748
1749 GateRef methodId = builder_.GetMethodId(glue, func);
1750 GateRef check = builder_.Equal(methodId, acc_.GetValueIn(gate, 1));
1751 builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT2);
1752 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1753 }
1754
LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate,GateRef glue)1755 void TypedHCRLowering::LowerJSNoGCFastCallThisTargetTypeCheck(GateRef gate, GateRef glue)
1756 {
1757 Environment env(gate, circuit_, &builder_);
1758 Label checkAlreadyDeopt(&builder_);
1759 Label exit(&builder_);
1760 GateRef frameState = GetFrameState(gate);
1761 auto func = acc_.GetValueIn(gate, 0);
1762 builder_.IsCallableCheck(func, frameState);
1763 CallTargetIsCompiledCheck(func, frameState, &checkAlreadyDeopt, &exit);
1764
1765 GateRef methodId = builder_.GetMethodId(glue, func);
1766 GateRef check = builder_.Equal(methodId, acc_.GetValueIn(gate, 1));
1767 builder_.DeoptCheck(check, frameState, DeoptType::NOTJSFASTCALLTGT3);
1768 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1769 }
1770
LowerJSNewObjRangeCallTargetCheck(GateRef gate,GateRef glue)1771 void TypedHCRLowering::LowerJSNewObjRangeCallTargetCheck(GateRef gate, GateRef glue)
1772 {
1773 Environment env(gate, circuit_, &builder_);
1774 GateRef frameState = GetFrameState(gate);
1775 auto ctor = acc_.GetValueIn(gate, 0);
1776 builder_.HeapObjectCheck(ctor, frameState);
1777 GateRef isJsFunc = builder_.IsJSFunction(glue, ctor);
1778 builder_.DeoptCheck(isJsFunc, frameState, DeoptType::NOTJSNEWCALLTGT);
1779 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1780 }
1781
LowerCallTargetCheck(GateRef gate)1782 void TypedHCRLowering::LowerCallTargetCheck(GateRef gate)
1783 {
1784 Environment env(gate, circuit_, &builder_);
1785 GateRef frameState = GetFrameState(gate);
1786
1787 BuiltinLowering lowering(circuit_, builder_.GetCompilationConfig(), traceBuiltins_);
1788 GateRef funcheck = lowering.LowerCallTargetCheck(&env, gate);
1789 GateRef check = lowering.CheckPara(gate, funcheck);
1790 builder_.DeoptCheck(check, frameState, DeoptType::NOTCALLTGT1);
1791
1792 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1793 }
1794
LowerJSInlineTargetTypeCheck(GateRef gate,GateRef glue)1795 void TypedHCRLowering::LowerJSInlineTargetTypeCheck(GateRef gate, GateRef glue)
1796 {
1797 Environment env(gate, circuit_, &builder_);
1798 GateRef frameState = GetFrameState(gate);
1799 auto func = acc_.GetValueIn(gate, 0);
1800 builder_.HeapObjectCheck(func, frameState);
1801 GateRef isFunction = builder_.IsJSFunction(glue, func);
1802 builder_.DeoptCheck(isFunction, frameState, DeoptType::NOTJSFUNCTION);
1803 GateRef check = builder_.Equal(builder_.GetMethodId(glue, func), acc_.GetValueIn(gate, 1));
1804 builder_.DeoptCheck(check, frameState, DeoptType::INLINEFAIL1);
1805 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1806 }
1807
LowerJSInlineTargetHeapConstantCheck(GateRef gate)1808 void TypedHCRLowering::LowerJSInlineTargetHeapConstantCheck(GateRef gate)
1809 {
1810 Environment env(gate, circuit_, &builder_);
1811 GateRef frameState = GetFrameState(gate);
1812 auto func = acc_.GetValueIn(gate, 0);
1813 auto heapConstant = acc_.GetValueIn(gate, 1); // 1: the second value, heapConstant
1814 builder_.DeoptCheck(builder_.Equal(func, heapConstant), frameState, DeoptType::NOTCALLTARGETHEAPOBJECT);
1815 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1816 }
1817
LowerInlineSuperCtorCheck(GateRef glue,GateRef gate)1818 void TypedHCRLowering::LowerInlineSuperCtorCheck(GateRef glue, GateRef gate)
1819 {
1820 Environment env(gate, circuit_, &builder_);
1821 GateRef frameState = GetFrameState(gate);
1822 auto func = acc_.GetValueIn(gate, 0);
1823 GateRef newTarget = acc_.GetValueIn(gate, 2); // 2: newTarget
1824 GateRef constant = acc_.GetValueIn(gate, 1); // 1: Heap constant or method ID
1825 GateRef check = Circuit::NullGate();
1826 if (acc_.GetOpCode(constant) == OpCode::HEAP_CONSTANT) {
1827 check = LogicAndBuilder(&env)
1828 .And(builder_.Equal(func, constant))
1829 .And(builder_.BoolNot(builder_.TaggedIsUndefined(newTarget)))
1830 .Done();
1831 } else {
1832 builder_.HeapObjectCheck(func, frameState);
1833 check = LogicAndBuilder(&env)
1834 .And(builder_.IsJSFunction(glue, func))
1835 .And(builder_.IsConstructor(glue, func))
1836 .And(builder_.Equal(builder_.GetMethodId(glue, func), acc_.GetValueIn(gate, 1)))
1837 .And(builder_.BoolNot(builder_.TaggedIsUndefined(newTarget)))
1838 .Done();
1839 }
1840 builder_.DeoptCheck(check, frameState, DeoptType::INLINESUPERFAIL);
1841 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
1842 }
1843
LowerTypedNewAllocateThis(GateRef gate,GateRef glue)1844 void TypedHCRLowering::LowerTypedNewAllocateThis(GateRef gate, GateRef glue)
1845 {
1846 Environment env(gate, circuit_, &builder_);
1847 ArgumentAccessor *argAcc = circuit_->GetArgumentAccessor();
1848 GateRef ctor = acc_.GetValueIn(gate, 0); // 0: 1st argument
1849 GateRef ihclass = acc_.GetValueIn(gate, 1); // 1: 2nd argument
1850 GateRef size = acc_.GetValueIn(gate, 2); // 2: 3rd argument
1851 Label isBase(&builder_);
1852 Label exit(&builder_);
1853 DEFVALUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1854 BRANCH_CIR(builder_.IsBase(glue, ctor), &isBase, &exit);
1855 builder_.Bind(&isBase);
1856 if (compilationEnv_->IsJitCompiler()) {
1857 thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewJSObject, {glue, ihclass, size});
1858 builder_.Jump(&exit);
1859 } else {
1860 NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment());
1861 newBuilder.SetParameters(glue, 0);
1862 newBuilder.NewJSObject(&thisObj, &exit, ihclass, size);
1863 }
1864 builder_.Bind(&exit);
1865 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *thisObj);
1866 }
1867
LowerTypedSuperAllocateThis(GateRef gate,GateRef glue)1868 void TypedHCRLowering::LowerTypedSuperAllocateThis(GateRef gate, GateRef glue)
1869 {
1870 Environment env(gate, circuit_, &builder_);
1871 GateRef superCtor = acc_.GetValueIn(gate, 0);
1872 GateRef newTarget = acc_.GetValueIn(gate, 1);
1873
1874 DEFVALUE(thisObj, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
1875 Label allocate(&builder_);
1876 Label exit(&builder_);
1877
1878 GateRef isBase = builder_.IsBase(glue, superCtor);
1879 BRANCH_CIR(isBase, &allocate, &exit);
1880 builder_.Bind(&allocate);
1881 {
1882 thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::FastSuperAllocateThis,
1883 { glue, superCtor, newTarget });
1884 builder_.Jump(&exit);
1885 }
1886 builder_.Bind(&exit);
1887 ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *thisObj);
1888 }
1889
LowerGetSuperConstructor(GateRef glue,GateRef gate)1890 void TypedHCRLowering::LowerGetSuperConstructor(GateRef glue, GateRef gate)
1891 {
1892 Environment env(gate, circuit_, &builder_);
1893 GateRef ctor = acc_.GetValueIn(gate, 0);
1894 GateRef hclass = builder_.LoadHClassByConstOffset(glue, ctor);
1895 GateRef superCtor = builder_.LoadPrototype(glue_, hclass);
1896 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), superCtor);
1897 }
1898
GetVarType(PropertyLookupResult plr)1899 VariableType TypedHCRLowering::GetVarType(PropertyLookupResult plr)
1900 {
1901 if (plr.GetRepresentation() == Representation::DOUBLE) {
1902 return kungfu::VariableType::FLOAT64();
1903 } else if (plr.GetRepresentation() == Representation::INT) {
1904 return kungfu::VariableType::INT32();
1905 } else {
1906 return kungfu::VariableType::INT64();
1907 }
1908 }
1909
GetLengthFromSupers(GateRef supers)1910 GateRef TypedHCRLowering::GetLengthFromSupers(GateRef supers)
1911 {
1912 return builder_.LoadConstOffset(VariableType::INT32(), supers, TaggedArray::EXTRA_LENGTH_OFFSET);
1913 }
1914
GetValueFromSupers(GateRef supers,size_t index)1915 GateRef TypedHCRLowering::GetValueFromSupers(GateRef supers, size_t index)
1916 {
1917 GateRef val = builder_.LoadFromTaggedArray(supers, index);
1918 return builder_.LoadObjectFromWeakRef(val);
1919 }
1920
CallAccessor(GateRef glue,GateRef gate,GateRef function,GateRef receiver,AccessorMode mode,GateRef value)1921 GateRef TypedHCRLowering::CallAccessor(GateRef glue, GateRef gate, GateRef function, GateRef receiver,
1922 AccessorMode mode, GateRef value)
1923 {
1924 if (g_isEnableCMCGC) {
1925 builder_.CallNGCRuntime(glue, RTSTUB_ID(CopyCallTarget), Gate::InvalidGateRef, {glue, function}, glue);
1926 }
1927 const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(JSCall));
1928 GateRef target = builder_.IntPtr(RTSTUB_ID(JSCall));
1929 GateRef newTarget = builder_.Undefined();
1930 GateRef argc = builder_.Int64(NUM_MANDATORY_JSFUNC_ARGS + (mode == AccessorMode::SETTER ? 1 : 0)); // 1: value
1931 GateRef argv = builder_.IntPtr(0);
1932 std::vector<GateRef> args { glue, argc, argv, function, newTarget, receiver };
1933 if (mode == AccessorMode::SETTER) {
1934 args.emplace_back(value);
1935 }
1936
1937 return builder_.Call(cs, glue, target, builder_.GetDepend(), args, gate);
1938 }
1939
ReplaceHirWithPendingException(GateRef hirGate,GateRef glue,GateRef state,GateRef depend,GateRef value)1940 void TypedHCRLowering::ReplaceHirWithPendingException(GateRef hirGate, GateRef glue, GateRef state, GateRef depend,
1941 GateRef value)
1942 {
1943 auto condition = builder_.HasPendingException(glue, compilationEnv_);
1944 GateRef ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
1945 GateRef ifTrue = builder_.IfTrue(ifBranch);
1946 GateRef ifFalse = builder_.IfFalse(ifBranch);
1947 GateRef eDepend = builder_.DependRelay(ifTrue, depend);
1948 GateRef sDepend = builder_.DependRelay(ifFalse, depend);
1949
1950 StateDepend success(ifFalse, sDepend);
1951 StateDepend exception(ifTrue, eDepend);
1952 acc_.ReplaceHirWithIfBranch(hirGate, success, exception, value);
1953 }
1954
LowerLookupHolder(GateRef glue,GateRef gate)1955 void TypedHCRLowering::LowerLookupHolder(GateRef glue, GateRef gate)
1956 {
1957 Environment env(gate, circuit_, &builder_);
1958 ASSERT(acc_.GetNumValueIn(gate) == 3); // 3: receiver, holderHC, jsFunc
1959 GateRef receiver = acc_.GetValueIn(gate, 0);
1960 GateRef holderHCIndex = acc_.GetValueIn(gate, 1);
1961 GateRef unsharedConstPool = acc_.GetValueIn(gate, 2); // 2: constpool
1962 GateRef holderHC = builder_.LoadHClassFromConstpool(unsharedConstPool,
1963 acc_.GetConstantValue(holderHCIndex));
1964 GateRef frameState = acc_.GetFrameState(gate);
1965 DEFVALUE(holder, (&builder_), VariableType::JS_ANY(), receiver);
1966 Label loopHead(&builder_);
1967 Label exit(&builder_);
1968 Label lookUpProto(&builder_);
1969 builder_.Jump(&loopHead);
1970
1971 builder_.LoopBegin(&loopHead);
1972 builder_.DeoptCheck(builder_.TaggedIsNotNull(*holder), frameState, DeoptType::INCONSISTENTHCLASS13);
1973 auto curHC = builder_.LoadHClassByConstOffset(glue, *holder);
1974 BRANCH_CIR(builder_.Equal(curHC, holderHC), &exit, &lookUpProto);
1975
1976 builder_.Bind(&lookUpProto);
1977 holder = builder_.LoadPrototype(glue_, curHC);
1978 builder_.LoopEnd(&loopHead);
1979
1980 builder_.Bind(&exit);
1981 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *holder);
1982 }
1983
LowerLoadGetter(GateRef gate,GateRef glue)1984 void TypedHCRLowering::LowerLoadGetter(GateRef gate, GateRef glue)
1985 {
1986 Environment env(gate, circuit_, &builder_);
1987 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: holder, plr
1988 GateRef holder = acc_.GetValueIn(gate, 0);
1989 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
1990 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
1991 ASSERT(plr.IsAccessor());
1992
1993 GateRef getter;
1994 if (plr.IsInlinedProps()) {
1995 auto acceessorData = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
1996 getter = builder_.LoadConstOffset(VariableType::JS_ANY(), acceessorData, AccessorData::GETTER_OFFSET);
1997 } else {
1998 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
1999 auto acceessorData = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
2000 getter = builder_.LoadConstOffset(VariableType::JS_ANY(), acceessorData, AccessorData::GETTER_OFFSET);
2001 }
2002 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), getter);
2003 }
2004
LowerLoadSetter(GateRef gate,GateRef glue)2005 void TypedHCRLowering::LowerLoadSetter(GateRef gate, GateRef glue)
2006 {
2007 Environment env(gate, circuit_, &builder_);
2008 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: holder, plr
2009 GateRef holder = acc_.GetValueIn(gate, 0);
2010 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
2011 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
2012 ASSERT(plr.IsAccessor());
2013
2014 GateRef setter;
2015 if (plr.IsInlinedProps()) {
2016 auto acceessorData = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
2017 setter = builder_.LoadConstOffset(VariableType::JS_ANY(), acceessorData, AccessorData::SETTER_OFFSET);
2018 } else {
2019 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
2020 auto acceessorData = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
2021 setter = builder_.LoadConstOffset(VariableType::JS_ANY(), acceessorData, AccessorData::SETTER_OFFSET);
2022 }
2023 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), setter);
2024 }
2025
LowerPrototypeCheck(GateRef glue,GateRef gate)2026 void TypedHCRLowering::LowerPrototypeCheck(GateRef glue, GateRef gate)
2027 {
2028 Environment env(gate, circuit_, &builder_);
2029 GateRef unsharedConstPool = acc_.GetValueIn(gate, 0);
2030 GateRef frameState = acc_.GetFrameState(gate);
2031
2032 uint32_t hclassIndex = acc_.GetHClassIndex(gate);
2033 auto expectedReceiverHC = builder_.LoadHClassFromConstpool(unsharedConstPool, hclassIndex);
2034
2035 auto prototype = builder_.LoadPrototype(glue_, expectedReceiverHC);
2036 auto protoHClass = builder_.LoadHClassByConstOffset(glue, prototype);
2037 auto marker = builder_.LoadProtoChangeMarker(glue, protoHClass);
2038 builder_.DeoptCheck(builder_.TaggedIsNotNull(marker), frameState, DeoptType::PROTOTYPECHANGED1);
2039 auto check = LogicAndBuilder(&env)
2040 .And(builder_.BoolNot(builder_.GetHasChanged(marker)))
2041 .And(builder_.BoolNot(builder_.GetAccessorHasChanged(marker)))
2042 .Done();
2043 builder_.DeoptCheck(check, frameState, DeoptType::INLINEFAIL2);
2044 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2045 return;
2046 }
2047
LowerStringEqual(GateRef gate,GateRef glue)2048 void TypedHCRLowering::LowerStringEqual(GateRef gate, GateRef glue)
2049 {
2050 Environment env(gate, circuit_, &builder_);
2051 GateRef left = acc_.GetValueIn(gate, 0);
2052 GateRef right = acc_.GetValueIn(gate, 1);
2053 GateRef leftLength = GetLengthFromString(left);
2054 GateRef rightLength = GetLengthFromString(right);
2055
2056 DEFVALUE(result, (&builder_), VariableType::BOOL(), builder_.False());
2057 Label lenEqual(&builder_);
2058 Label exit(&builder_);
2059 BRANCH_CIR(builder_.Equal(leftLength, rightLength), &lenEqual, &exit);
2060 builder_.Bind(&lenEqual);
2061 {
2062 result = builder_.CallStub(glue, gate, CommonStubCSigns::FastStringEqual,
2063 {glue, left, right, circuit_->GetGlobalEnvCache()});
2064 builder_.Jump(&exit);
2065 }
2066 builder_.Bind(&exit);
2067 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
2068 }
2069
LowerTypeOfCheck(GateRef gate)2070 void TypedHCRLowering::LowerTypeOfCheck(GateRef gate)
2071 {
2072 Environment env(gate, circuit_, &builder_);
2073 GateRef frameState = GetFrameState(gate);
2074 GateRef glue = glue_;
2075 GateRef value = acc_.GetValueIn(gate, 0);
2076 GateTypeAccessor accessor(acc_.TryGetValue(gate));
2077 ParamType type = accessor.GetParamType();
2078 GateRef check = Circuit::NullGate();
2079 if (type.IsNumberType()) {
2080 check = builder_.TaggedIsNumber(value);
2081 } else if (type.IsBooleanType()) {
2082 check = builder_.TaggedIsBoolean(value);
2083 } else if (type.IsNullType()) {
2084 check = builder_.TaggedIsNull(value);
2085 } else if (type.IsUndefinedType()) {
2086 check = builder_.TaggedIsUndefined(value);
2087 } else {
2088 // NOTICE-PGO: wx add support for builtin(Function Object ArrayKind)
2089 builder_.DeoptCheck(builder_.TaggedIsHeapObject(value, compilationEnv_),
2090 frameState, DeoptType::INCONSISTENTTYPE1);
2091 if (type.IsStringType()) {
2092 check = builder_.TaggedIsString(glue, value);
2093 } else if (type.IsBigIntType()) {
2094 check = builder_.IsJsType(glue, value, JSType::BIGINT);
2095 } else if (type.IsSymbolType()) {
2096 check = builder_.IsJsType(glue, value, JSType::SYMBOL);
2097 } else {
2098 UNREACHABLE();
2099 }
2100 }
2101
2102 builder_.DeoptCheck(check, frameState, DeoptType::INCONSISTENTTYPE1);
2103 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2104 }
2105
LowerTypeOf(GateRef gate,GateRef glue)2106 void TypedHCRLowering::LowerTypeOf(GateRef gate, GateRef glue)
2107 {
2108 Environment env(gate, circuit_, &builder_);
2109 GateTypeAccessor accessor(acc_.TryGetValue(gate));
2110 ParamType type = accessor.GetParamType();
2111 GateRef gConstAddr = builder_.LoadWithoutBarrier(VariableType::JS_POINTER(), glue,
2112 builder_.IntPtr(JSThread::GlueData::GetGlobalConstOffset(builder_.GetCompilationConfig()->Is32Bit())));
2113 ConstantIndex index;
2114 // NOTICE-PGO: wx add support for builtin(Function Object ArrayKind)
2115 if (type.IsNumberType()) {
2116 index = ConstantIndex::NUMBER_STRING_INDEX;
2117 } else if (type.IsBooleanType()) {
2118 index = ConstantIndex::BOOLEAN_STRING_INDEX;
2119 } else if (type.IsNullType()) {
2120 index = ConstantIndex::OBJECT_STRING_INDEX;
2121 } else if (type.IsUndefinedType()) {
2122 index = ConstantIndex::UNDEFINED_STRING_INDEX;
2123 } else if (type.IsStringType()) {
2124 index = ConstantIndex::STRING_STRING_INDEX;
2125 } else if (type.IsBigIntType()) {
2126 index = ConstantIndex::BIGINT_STRING_INDEX;
2127 } else if (type.IsSymbolType()) {
2128 index = ConstantIndex::SYMBOL_STRING_INDEX;
2129 } else {
2130 UNREACHABLE();
2131 }
2132
2133 GateRef result = builder_.LoadWithoutBarrier(VariableType::JS_POINTER(), gConstAddr,
2134 builder_.GetGlobalConstantOffset(index));
2135 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
2136 }
2137
LowerTypedConstructorCheck(GateRef gate,GateRef glue)2138 void TypedHCRLowering::LowerTypedConstructorCheck(GateRef gate, GateRef glue)
2139 {
2140 static const std::map<size_t, DeoptType> deoptType = {
2141 {GlobalEnv::ARRAY_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORARRAY},
2142 {GlobalEnv::OBJECT_FUNCTION_INDEX, DeoptType::NEWBUILTINCTOROBJECT},
2143 {GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORFLOAT32ARRAY},
2144 {GlobalEnv::BOOLEAN_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORBOOLEAN},
2145 {GlobalEnv::BUILTINS_MAP_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORMAP},
2146 {GlobalEnv::BUILTINS_SET_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORSET},
2147 {GlobalEnv::DATE_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORDATE},
2148 {GlobalEnv::ERROR_FUNCTION_INDEX, DeoptType::NEWBUILTINCTORERROR},
2149 };
2150 Environment env(gate, circuit_, &builder_);
2151 size_t functionIndex = static_cast<size_t>(acc_.TryGetValue(gate));
2152 GateRef frameState = GetFrameState(gate);
2153 GateRef newTarget = acc_.GetValueIn(gate, 0);
2154 GateRef globalEnv = circuit_->GetGlobalEnvCache();
2155 GateRef builtinFunc = builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, functionIndex);
2156 GateRef check = builder_.Equal(builtinFunc, newTarget);
2157 auto type =
2158 deoptType.find(functionIndex) != deoptType.end() ? deoptType.at(functionIndex) : DeoptType::NEWBUILTINCTORFAIL1;
2159 builder_.DeoptCheck(check, frameState, type);
2160 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2161 }
2162
LowerArrayConstructorCheck(GateRef gate,GateRef glue)2163 void TypedHCRLowering::LowerArrayConstructorCheck(GateRef gate, GateRef glue)
2164 {
2165 Environment env(gate, circuit_, &builder_);
2166 GateRef frameState = GetFrameState(gate);
2167 GateRef newTarget = acc_.GetValueIn(gate, 0);
2168 Label isHeapObject(&builder_);
2169 Label exit(&builder_);
2170 DEFVALUE(check, (&builder_), VariableType::BOOL(), builder_.True());
2171 check = builder_.TaggedIsHeapObject(newTarget, compilationEnv_);
2172 BRANCH_CIR(*check, &isHeapObject, &exit);
2173 builder_.Bind(&isHeapObject);
2174 {
2175 Label isJSFunction(&builder_);
2176 check = builder_.IsJSFunction(glue, newTarget);
2177 BRANCH_CIR(*check, &isJSFunction, &exit);
2178 builder_.Bind(&isJSFunction);
2179 {
2180 Label getHclass(&builder_);
2181 GateRef globalEnv = circuit_->GetGlobalEnvCache();
2182 GateRef arrayFunc =
2183 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
2184 check = builder_.Equal(arrayFunc, newTarget);
2185 BRANCH_CIR(*check, &getHclass, &exit);
2186 builder_.Bind(&getHclass);
2187 {
2188 GateRef intialHClass = builder_.Load(VariableType::JS_ANY(), glue, newTarget,
2189 builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2190 check = builder_.IsJSHClass(glue, intialHClass);
2191 builder_.Jump(&exit);
2192 }
2193 }
2194 }
2195 builder_.Bind(&exit);
2196 builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORARRAY);
2197 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2198 }
2199
LowerArrayConstructor(GateRef gate,GateRef glue)2200 void TypedHCRLowering::LowerArrayConstructor(GateRef gate, GateRef glue)
2201 {
2202 Environment env(gate, circuit_, &builder_);
2203 if (acc_.GetNumValueIn(gate) == 1) {
2204 NewArrayConstructorWithNoArgs(gate, glue);
2205 return;
2206 }
2207 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: new target and arg0
2208 DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2209 Label slowPath(&builder_);
2210 Label exit(&builder_);
2211 GateRef newTarget = acc_.GetValueIn(gate, 0);
2212 GateRef arg0 = acc_.GetValueIn(gate, 1);
2213 GateRef intialHClass =
2214 builder_.Load(VariableType::JS_ANY(), glue, newTarget, builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2215 DEFVALUE(arrayLength, (&builder_), VariableType::INT64(), builder_.Int64(0));
2216 Label argIsNumber(&builder_);
2217 Label arrayCreate(&builder_);
2218 BRANCH_CIR(builder_.TaggedIsNumber(arg0), &argIsNumber, &slowPath);
2219 builder_.Bind(&argIsNumber);
2220 {
2221 Label argIsInt(&builder_);
2222 Label argIsDouble(&builder_);
2223 BRANCH_CIR(builder_.TaggedIsInt(arg0), &argIsInt, &argIsDouble);
2224 builder_.Bind(&argIsInt);
2225 {
2226 Label validIntLength(&builder_);
2227 GateRef intLen = builder_.GetInt64OfTInt(arg0);
2228 GateRef isGEZero = builder_.Int64GreaterThanOrEqual(intLen, builder_.Int64(0));
2229 GateRef isLEMaxLen = builder_.Int64LessThanOrEqual(intLen, builder_.Int64(JSArray::MAX_ARRAY_INDEX));
2230 BRANCH_CIR(builder_.BitAnd(isGEZero, isLEMaxLen), &validIntLength, &slowPath);
2231 builder_.Bind(&validIntLength);
2232 {
2233 arrayLength = intLen;
2234 builder_.Jump(&arrayCreate);
2235 }
2236 }
2237 builder_.Bind(&argIsDouble);
2238 {
2239 Label validDoubleLength(&builder_);
2240 GateRef doubleLength = builder_.GetDoubleOfTDouble(arg0);
2241 GateRef doubleToInt = builder_.TruncDoubleToInt(glue, doubleLength, base::INT32_BITS);
2242 GateRef intToDouble = builder_.CastInt64ToFloat64(builder_.SExtInt32ToInt64(doubleToInt));
2243 GateRef doubleEqual = builder_.DoubleEqual(doubleLength, intToDouble);
2244 GateRef doubleLEMaxLen =
2245 builder_.DoubleLessThanOrEqual(doubleLength, builder_.Double(JSArray::MAX_ARRAY_INDEX));
2246 BRANCH_CIR(builder_.BitAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, &slowPath);
2247 builder_.Bind(&validDoubleLength);
2248 {
2249 arrayLength = builder_.SExtInt32ToInt64(doubleToInt);
2250 builder_.Jump(&arrayCreate);
2251 }
2252 }
2253 }
2254 builder_.Bind(&arrayCreate);
2255 {
2256 Label lengthValid(&builder_);
2257 BRANCH_CIR(
2258 builder_.Int64GreaterThan(*arrayLength, builder_.Int64(JSObject::MAX_GAP)), &slowPath, &lengthValid);
2259 builder_.Bind(&lengthValid);
2260 {
2261 NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2262 newBuilder.SetParameters(glue, 0);
2263 res = newBuilder.NewJSArrayWithSize(intialHClass, *arrayLength);
2264 GateRef lengthOffset = builder_.IntPtr(JSArray::LENGTH_OFFSET);
2265 builder_.Store(VariableType::INT32(), glue, *res, lengthOffset, builder_.TruncInt64ToInt32(*arrayLength));
2266 GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2267 builder_.SetPropertyInlinedProps(glue, *res, intialHClass, accessor,
2268 builder_.Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY());
2269 builder_.SetExtensibleToBitfield(glue, *res, true);
2270 builder_.Jump(&exit);
2271 }
2272 }
2273 builder_.Bind(&slowPath);
2274 {
2275 size_t range = acc_.GetNumValueIn(gate);
2276 std::vector<GateRef> args(range);
2277 for (size_t i = 0; i < range; ++i) {
2278 args[i] = acc_.GetValueIn(gate, i);
2279 }
2280 res = LowerCallRuntime(glue, gate, RTSTUB_ID(OptNewObjRange), args, true);
2281 builder_.Jump(&exit);
2282 }
2283 builder_.Bind(&exit);
2284 ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), *res);
2285 }
2286
LowerFloat32ArrayConstructorCheck(GateRef gate,GateRef glue)2287 void TypedHCRLowering::LowerFloat32ArrayConstructorCheck(GateRef gate, GateRef glue)
2288 {
2289 Environment env(gate, circuit_, &builder_);
2290 GateRef frameState = GetFrameState(gate);
2291 GateRef newTarget = acc_.GetValueIn(gate, 0);
2292 GateRef globalEnv = circuit_->GetGlobalEnvCache();
2293 GateRef arrayFunc =
2294 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::FLOAT32_ARRAY_FUNCTION_INDEX);
2295 GateRef check = builder_.Equal(arrayFunc, newTarget);
2296 builder_.DeoptCheck(check, frameState, DeoptType::NEWBUILTINCTORFLOAT32ARRAY);
2297 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2298 }
2299
NewFloat32ArrayConstructorWithNoArgs(GateRef gate,GateRef glue)2300 void TypedHCRLowering::NewFloat32ArrayConstructorWithNoArgs(GateRef gate, GateRef glue)
2301 {
2302 NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2303 newBuilder.SetParameters(glue, 0);
2304 GateRef res = newBuilder.NewFloat32ArrayWithSize(glue, builder_.Int32(0));
2305 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), res);
2306 }
2307
ConvertFloat32ArrayConstructorLength(GateRef len,Variable * arrayLength,Label * arrayCreate,Label * slowPath)2308 void TypedHCRLowering::ConvertFloat32ArrayConstructorLength(GateRef len, Variable *arrayLength,
2309 Label *arrayCreate, Label *slowPath)
2310 {
2311 Label argIsNumber(&builder_);
2312 BRANCH_CIR(builder_.TaggedIsNumber(len), &argIsNumber, slowPath);
2313 builder_.Bind(&argIsNumber);
2314 {
2315 Label argIsInt(&builder_);
2316 Label argIsDouble(&builder_);
2317 BRANCH_CIR(builder_.TaggedIsInt(len), &argIsInt, &argIsDouble);
2318 builder_.Bind(&argIsInt);
2319 {
2320 Label validIntLength(&builder_);
2321 GateRef intLen = builder_.GetInt64OfTInt(len);
2322 GateRef isGEZero = builder_.Int64GreaterThanOrEqual(intLen, builder_.Int64(0));
2323 GateRef isLEMaxLen = builder_.Int64LessThanOrEqual(intLen, builder_.Int64(JSObject::MAX_GAP));
2324 BRANCH_CIR(builder_.BitAnd(isGEZero, isLEMaxLen), &validIntLength, slowPath);
2325 builder_.Bind(&validIntLength);
2326 {
2327 *arrayLength = intLen;
2328 builder_.Jump(arrayCreate);
2329 }
2330 }
2331 builder_.Bind(&argIsDouble);
2332 {
2333 Label validDoubleLength(&builder_);
2334 GateRef doubleLength = builder_.GetDoubleOfTDouble(len);
2335 GateRef doubleToInt = builder_.TruncDoubleToInt(glue_, doubleLength, base::INT32_BITS);
2336 GateRef intToDouble = builder_.CastInt64ToFloat64(builder_.SExtInt32ToInt64(doubleToInt));
2337 GateRef doubleEqual = builder_.DoubleEqual(doubleLength, intToDouble);
2338 GateRef doubleLEMaxLen =
2339 builder_.DoubleLessThanOrEqual(doubleLength, builder_.Double(JSObject::MAX_GAP));
2340 BRANCH_CIR(builder_.BitAnd(doubleEqual, doubleLEMaxLen), &validDoubleLength, slowPath);
2341 builder_.Bind(&validDoubleLength);
2342 {
2343 *arrayLength = builder_.SExtInt32ToInt64(doubleToInt);
2344 builder_.Jump(arrayCreate);
2345 }
2346 }
2347 }
2348 }
2349
LowerFloat32ArrayConstructor(GateRef gate,GateRef glue)2350 void TypedHCRLowering::LowerFloat32ArrayConstructor(GateRef gate, GateRef glue)
2351 {
2352 Environment env(gate, circuit_, &builder_);
2353 if (compilationEnv_->IsJitCompiler()) {
2354 GateRef res = Circuit::NullGate();
2355 if (acc_.GetNumValueIn(gate) == 1) {
2356 res = builder_.CallStub(glue, gate, CommonStubCSigns::NewFloat32ArrayWithNoArgs,
2357 {glue, circuit_->GetGlobalEnvCache()}, "NewFloat32ArrayWithNoArgs stub");
2358 } else {
2359 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: new target and arg0
2360 res = builder_.CallStub(
2361 glue, gate, CommonStubCSigns::NewFloat32Array,
2362 {glue, acc_.GetValueIn(gate, 0), acc_.GetValueIn(gate, 1), circuit_->GetGlobalEnvCache()},
2363 "NewFloat32Array stub");
2364 }
2365 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), res);
2366 return;
2367 }
2368 if (acc_.GetNumValueIn(gate) == 1) {
2369 NewFloat32ArrayConstructorWithNoArgs(gate, glue);
2370 return;
2371 }
2372 ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: new target and arg0
2373 DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2374 Label slowPath(&builder_);
2375 Label exit(&builder_);
2376 GateRef ctor = acc_.GetValueIn(gate, 0);
2377 GateRef arg0 = acc_.GetValueIn(gate, 1);
2378 DEFVALUE(arrayLength, (&builder_), VariableType::INT64(), builder_.Int64(0));
2379 Label arrayCreateByLength(&builder_);
2380 Label arrayCreate(&builder_);
2381 ConvertFloat32ArrayConstructorLength(arg0, &arrayLength, &arrayCreateByLength, &arrayCreate);
2382 builder_.Bind(&arrayCreateByLength);
2383 {
2384 NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2385 newBuilder.SetParameters(glue, 0);
2386 GateRef truncedLength = builder_.TruncInt64ToInt32(*arrayLength);
2387 res = newBuilder.NewFloat32ArrayWithSize(glue, truncedLength);
2388 builder_.Jump(&exit);
2389 }
2390 builder_.Bind(&arrayCreate);
2391 {
2392 NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2393 newBuilder.SetParameters(glue, 0);
2394 GateRef thisObj = newBuilder.NewFloat32ArrayObj(glue);
2395 GateRef argc = builder_.Int64(4); // 4: means func newtarget thisObj arg0
2396 GateRef argv = builder_.IntPtr(0);
2397 std::vector<GateRef> args { glue, argc, argv, ctor, ctor, thisObj, arg0 };
2398 res = builder_.CallNew(gate, args);
2399 builder_.Jump(&exit);
2400 }
2401 builder_.Bind(&exit);
2402 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
2403 }
2404
NewArrayConstructorWithNoArgs(GateRef gate,GateRef glue)2405 void TypedHCRLowering::NewArrayConstructorWithNoArgs(GateRef gate, GateRef glue)
2406 {
2407 GateRef newTarget = acc_.GetValueIn(gate, 0);
2408 GateRef intialHClass =
2409 builder_.Load(VariableType::JS_ANY(), glue, newTarget, builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2410 GateRef arrayLength = builder_.Int64(0);
2411 NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment(), circuit_->GetGlobalEnvCache());
2412 newBuilder.SetParameters(glue, 0);
2413 GateRef res = newBuilder.NewJSArrayWithSize(intialHClass, arrayLength);
2414 GateRef lengthOffset = builder_.IntPtr(JSArray::LENGTH_OFFSET);
2415 builder_.Store(VariableType::INT32(), glue, res, lengthOffset, builder_.TruncInt64ToInt32(arrayLength));
2416 GateRef accessor = builder_.GetGlobalConstantValue(ConstantIndex::ARRAY_LENGTH_ACCESSOR);
2417 builder_.SetPropertyInlinedProps(glue, res, intialHClass, accessor,
2418 builder_.Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY());
2419 builder_.SetExtensibleToBitfield(glue, res, true);
2420 ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), res);
2421 }
2422
LowerObjectConstructorCheck(GateRef gate,GateRef glue)2423 void TypedHCRLowering::LowerObjectConstructorCheck(GateRef gate, GateRef glue)
2424 {
2425 Environment env(gate, circuit_, &builder_);
2426 GateRef frameState = GetFrameState(gate);
2427 GateRef newTarget = acc_.GetValueIn(gate, 0);
2428 Label isHeapObject(&builder_);
2429 Label exit(&builder_);
2430 DEFVALUE(check, (&builder_), VariableType::BOOL(), builder_.True());
2431 check = builder_.TaggedIsHeapObject(newTarget, compilationEnv_);
2432 BRANCH_CIR(*check, &isHeapObject, &exit);
2433 builder_.Bind(&isHeapObject);
2434 {
2435 Label isJSFunction(&builder_);
2436 check = builder_.IsJSFunction(glue, newTarget);
2437 BRANCH_CIR(*check, &isJSFunction, &exit);
2438 builder_.Bind(&isJSFunction);
2439 {
2440 Label getHclass(&builder_);
2441 GateRef globalEnv = circuit_->GetGlobalEnvCache();
2442 GateRef targetFunc =
2443 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::OBJECT_FUNCTION_INDEX);
2444 check = builder_.Equal(targetFunc, newTarget);
2445 BRANCH_CIR(*check, &getHclass, &exit);
2446 builder_.Bind(&getHclass);
2447 {
2448 GateRef intialHClass = builder_.Load(VariableType::JS_ANY(), glue, newTarget,
2449 builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2450 check = builder_.IsJSHClass(glue, intialHClass);
2451 builder_.Jump(&exit);
2452 }
2453 }
2454 }
2455 builder_.Bind(&exit);
2456 builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTOROBJECT);
2457 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2458 }
2459
LowerObjectConstructor(GateRef gate,GateRef glue)2460 void TypedHCRLowering::LowerObjectConstructor(GateRef gate, GateRef glue)
2461 {
2462 Environment env(gate, circuit_, &builder_);
2463 GateRef value = builder_.Undefined();
2464 ASSERT(acc_.GetNumValueIn(gate) <= 2); // 2: new target and arg0
2465 if (acc_.GetNumValueIn(gate) > 1) {
2466 value = acc_.GetValueIn(gate, 1);
2467 }
2468 DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2469 Label slowPath(&builder_);
2470 Label exit(&builder_);
2471
2472 Label isHeapObj(&builder_);
2473 Label notHeapObj(&builder_);
2474 BRANCH_CIR(builder_.TaggedIsHeapObject(value, compilationEnv_), &isHeapObj, ¬HeapObj);
2475 builder_.Bind(&isHeapObj);
2476 {
2477 Label isEcmaObj(&builder_);
2478 Label notEcmaObj(&builder_);
2479 BRANCH_CIR(builder_.TaggedObjectIsEcmaObject(glue, value), &isEcmaObj, ¬EcmaObj);
2480 builder_.Bind(&isEcmaObj);
2481 {
2482 res = value;
2483 builder_.Jump(&exit);
2484 }
2485 builder_.Bind(¬EcmaObj);
2486 {
2487 Label isSymbol(&builder_);
2488 Label notSymbol(&builder_);
2489 BRANCH_CIR(builder_.TaggedIsSymbol(glue, value), &isSymbol, ¬Symbol);
2490 builder_.Bind(&isSymbol);
2491 {
2492 res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_SYMBOL, glue, value);
2493 builder_.Jump(&exit);
2494 }
2495 builder_.Bind(¬Symbol);
2496 {
2497 Label isBigInt(&builder_);
2498 BRANCH_CIR(builder_.TaggedIsBigInt(glue, value), &isBigInt, &slowPath);
2499 builder_.Bind(&isBigInt);
2500 {
2501 res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_BIGINT, glue, value);
2502 builder_.Jump(&exit);
2503 }
2504 }
2505 }
2506 }
2507 builder_.Bind(¬HeapObj);
2508 {
2509 Label isNumber(&builder_);
2510 Label notNumber(&builder_);
2511 BRANCH_CIR(builder_.TaggedIsNumber(value), &isNumber, ¬Number);
2512 builder_.Bind(&isNumber);
2513 {
2514 res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_NUMBER, glue, value);
2515 builder_.Jump(&exit);
2516 }
2517 builder_.Bind(¬Number);
2518 {
2519 Label isBoolean(&builder_);
2520 Label notBoolean(&builder_);
2521 BRANCH_CIR(builder_.TaggedIsBoolean(value), &isBoolean, ¬Boolean);
2522 builder_.Bind(&isBoolean);
2523 {
2524 res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_BOOLEAN, glue, value);
2525 builder_.Jump(&exit);
2526 }
2527 builder_.Bind(¬Boolean);
2528 {
2529 Label isNullOrUndefined(&builder_);
2530 BRANCH_CIR(builder_.TaggedIsUndefinedOrNull(value), &isNullOrUndefined, &slowPath);
2531 builder_.Bind(&isNullOrUndefined);
2532 {
2533 GateRef globalEnv = circuit_->GetGlobalEnvCache();
2534 GateRef objectFunctionPrototype = builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue,
2535 globalEnv, GlobalEnv::OBJECT_FUNCTION_PROTOTYPE_INDEX);
2536 res = builder_.OrdinaryNewJSObjectCreate(glue, objectFunctionPrototype);
2537 builder_.Jump(&exit);
2538 }
2539 }
2540 }
2541 }
2542 builder_.Bind(&slowPath);
2543 {
2544 size_t range = acc_.GetNumValueIn(gate);
2545 std::vector<GateRef> args(range);
2546 for (size_t i = 0; i < range; ++i) {
2547 args[i] = acc_.GetValueIn(gate, i);
2548 }
2549 res = LowerCallRuntime(glue, gate, RTSTUB_ID(OptNewObjRange), args, true);
2550 builder_.Jump(&exit);
2551 }
2552 builder_.Bind(&exit);
2553 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
2554 }
2555
LowerBooleanConstructorCheck(GateRef gate,GateRef glue)2556 void TypedHCRLowering::LowerBooleanConstructorCheck(GateRef gate, GateRef glue)
2557 {
2558 Environment env(gate, circuit_, &builder_);
2559 GateRef frameState = GetFrameState(gate);
2560 GateRef newTarget = acc_.GetValueIn(gate, 0);
2561 Label isHeapObject(&builder_);
2562 Label exit(&builder_);
2563 DEFVALUE(check, (&builder_), VariableType::BOOL(), builder_.True());
2564 check = builder_.TaggedIsHeapObject(newTarget, compilationEnv_);
2565 BRANCH_CIR(*check, &isHeapObject, &exit);
2566 builder_.Bind(&isHeapObject);
2567 {
2568 Label isJSFunction(&builder_);
2569 check = builder_.IsJSFunction(glue, newTarget);
2570 BRANCH_CIR(*check, &isJSFunction, &exit);
2571 builder_.Bind(&isJSFunction);
2572 {
2573 Label getHclass(&builder_);
2574 GateRef globalEnv = circuit_->GetGlobalEnvCache();
2575 GateRef booleanFunc =
2576 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
2577 check = builder_.Equal(booleanFunc, newTarget);
2578 BRANCH_CIR(*check, &getHclass, &exit);
2579 builder_.Bind(&getHclass);
2580 {
2581 GateRef intialHClass = builder_.Load(VariableType::JS_ANY(), glue, newTarget,
2582 builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2583 check = builder_.IsJSHClass(glue, intialHClass);
2584 builder_.Jump(&exit);
2585 }
2586 }
2587 }
2588 builder_.Bind(&exit);
2589 builder_.DeoptCheck(*check, frameState, DeoptType::NEWBUILTINCTORBOOLEAN);
2590 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2591 }
2592
LowerBooleanConstructor(GateRef gate,GateRef glue)2593 void TypedHCRLowering::LowerBooleanConstructor(GateRef gate, GateRef glue)
2594 {
2595 Environment env(gate, circuit_, &builder_);
2596 GateRef value = builder_.Undefined();
2597 ASSERT(acc_.GetNumValueIn(gate) <= 2); // 2: new target and arg0
2598 if (acc_.GetNumValueIn(gate) > 1) {
2599 value = acc_.GetValueIn(gate, 1);
2600 }
2601 DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2602 Label isBoolean(&builder_);
2603 Label slowPath(&builder_);
2604 Label exit(&builder_);
2605 BRANCH_CIR(builder_.TaggedIsBoolean(value), &isBoolean, &slowPath);
2606 builder_.Bind(&isBoolean);
2607 {
2608 res = NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_BOOLEAN, glue, value);
2609 builder_.Jump(&exit);
2610 }
2611 builder_.Bind(&slowPath);
2612 {
2613 size_t range = acc_.GetNumValueIn(gate);
2614 std::vector<GateRef> args(range);
2615 for (size_t i = 0; i < range; ++i) {
2616 args[i] = acc_.GetValueIn(gate, i);
2617 }
2618 res = LowerCallRuntime(glue, gate, RTSTUB_ID(OptNewObjRange), args, true);
2619 builder_.Jump(&exit);
2620 }
2621 builder_.Bind(&exit);
2622 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
2623 }
2624
NewJSPrimitiveRef(PrimitiveType type,GateRef glue,GateRef value)2625 GateRef TypedHCRLowering::NewJSPrimitiveRef(PrimitiveType type, GateRef glue, GateRef value)
2626 {
2627 GateRef globalEnv = circuit_->GetGlobalEnvCache();
2628 GateRef ctor = Circuit::NullGate();
2629 switch (type) {
2630 case PrimitiveType::PRIMITIVE_NUMBER: {
2631 ctor =
2632 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::NUMBER_FUNCTION_INDEX);
2633 break;
2634 }
2635 case PrimitiveType::PRIMITIVE_SYMBOL: {
2636 ctor =
2637 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::SYMBOL_FUNCTION_INDEX);
2638 break;
2639 }
2640 case PrimitiveType::PRIMITIVE_BOOLEAN: {
2641 ctor =
2642 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::BOOLEAN_FUNCTION_INDEX);
2643 break;
2644 }
2645 case PrimitiveType::PRIMITIVE_BIGINT: {
2646 ctor =
2647 builder_.GetGlobalEnvValue(VariableType::JS_ANY(), glue, globalEnv, GlobalEnv::BIGINT_FUNCTION_INDEX);
2648 break;
2649 }
2650 default: {
2651 LOG_ECMA(FATAL) << "this branch is unreachable " << static_cast<int>(type);
2652 UNREACHABLE();
2653 }
2654 }
2655 GateRef hclass =
2656 builder_.Load(VariableType::JS_ANY(), glue, ctor, builder_.IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
2657 NewObjectStubBuilder newBuilder(builder_.GetCurrentEnvironment());
2658 GateRef res = newBuilder.NewJSObject(glue, hclass);
2659 GateRef valueOffset = builder_.IntPtr(JSPrimitiveRef::VALUE_OFFSET);
2660 builder_.Store(VariableType::JS_ANY(), glue, res, valueOffset, value);
2661 return res;
2662 }
2663
ReplaceGateWithPendingException(GateRef glue,GateRef gate,GateRef state,GateRef depend,GateRef value)2664 void TypedHCRLowering::ReplaceGateWithPendingException(GateRef glue, GateRef gate, GateRef state, GateRef depend,
2665 GateRef value)
2666 {
2667 auto condition = builder_.HasPendingException(glue, compilationEnv_);
2668 GateRef ifBranch = builder_.Branch(state, condition, 1, BranchWeight::DEOPT_WEIGHT, "checkException");
2669 GateRef ifTrue = builder_.IfTrue(ifBranch);
2670 GateRef ifFalse = builder_.IfFalse(ifBranch);
2671 GateRef eDepend = builder_.DependRelay(ifTrue, depend);
2672 GateRef sDepend = builder_.DependRelay(ifFalse, depend);
2673
2674 StateDepend success(ifFalse, sDepend);
2675 StateDepend exception(ifTrue, eDepend);
2676 acc_.ReplaceHirWithIfBranch(gate, success, exception, value);
2677 }
2678
LowerLoadBuiltinObject(GateRef gate)2679 void TypedHCRLowering::LowerLoadBuiltinObject(GateRef gate)
2680 {
2681 if (!enableLoweringBuiltin_) {
2682 return;
2683 }
2684 Environment env(gate, circuit_, &builder_);
2685 auto frameState = GetFrameState(gate);
2686 GateRef glue = glue_;
2687 auto builtinEntriesOffset = JSThread::GlueData::GetBuiltinEntriesOffset(false);
2688 size_t index = acc_.GetIndex(gate);
2689 auto boxOffset = builtinEntriesOffset + BuiltinIndex::GetInstance().GetBuiltinBoxOffset(index);
2690 GateRef box = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, boxOffset);
2691 GateRef builtin = builder_.LoadConstOffset(VariableType::JS_POINTER(), box, PropertyBox::VALUE_OFFSET);
2692 auto builtinIsNotHole = builder_.TaggedIsNotHole(builtin);
2693 // attributes on globalThis may change, it will cause renew a PropertyBox, the old box will be abandoned
2694 // so we need deopt
2695 builder_.DeoptCheck(builtinIsNotHole, frameState, DeoptType::BUILTINISHOLE1);
2696 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), builtin);
2697 }
2698
LowerOrdinaryHasInstanceForJIT(GateRef gate,GateRef glue)2699 void TypedHCRLowering::LowerOrdinaryHasInstanceForJIT(GateRef gate, GateRef glue)
2700 {
2701 Environment env(gate, circuit_, &builder_);
2702 GateRef obj = acc_.GetValueIn(gate, 0);
2703 GateRef target = acc_.GetValueIn(gate, 1);
2704 auto result = builder_.CallStub(glue, gate, CommonStubCSigns::OrdinaryHasInstance,
2705 {glue, obj, target, circuit_->GetGlobalEnvCache()}, "OrdinaryHasInstance stub");
2706 ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), result);
2707 }
2708
LowerOrdinaryHasInstance(GateRef gate,GateRef glue)2709 void TypedHCRLowering::LowerOrdinaryHasInstance(GateRef gate, GateRef glue)
2710 {
2711 Environment env(gate, circuit_, &builder_);
2712 GateRef obj = acc_.GetValueIn(gate, 0);
2713 GateRef target = acc_.GetValueIn(gate, 1);
2714
2715 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
2716 DEFVALUE(object, (&builder_), VariableType::JS_ANY(), obj);
2717 Label exit(&builder_);
2718
2719 Label targetIsBoundFunction(&builder_);
2720 Label targetNotBoundFunction(&builder_);
2721 // 2. If C has a [[BoundTargetFunction]] internal slot, then
2722 // a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
2723 // b. Return InstanceofOperator(O,BC) (see 12.9.4).
2724 BRANCH_CIR(builder_.TaggedIsBoundFunction(glue, target), &targetIsBoundFunction, &targetNotBoundFunction);
2725 builder_.Bind(&targetIsBoundFunction);
2726 {
2727 GateRef boundTarget = builder_.LoadConstOffset(VariableType::JS_ANY(), target,
2728 JSBoundFunction::BOUND_TARGET_OFFSET);
2729 result = builder_.CallRuntime(glue, RTSTUB_ID(InstanceOf), Gate::InvalidGateRef,
2730 { obj, boundTarget }, gate);
2731 builder_.Jump(&exit);
2732 }
2733 builder_.Bind(&targetNotBoundFunction);
2734
2735 // 3. If Type(O) is not Object, return false
2736 Label objIsHeapObject(&builder_);
2737 Label objIsEcmaObject(&builder_);
2738 Label objNotEcmaObject(&builder_);
2739 BRANCH_CIR(builder_.TaggedIsHeapObject(obj, compilationEnv_), &objIsHeapObject, &objNotEcmaObject);
2740 builder_.Bind(&objIsHeapObject);
2741 BRANCH_CIR(builder_.TaggedObjectIsEcmaObject(glue, obj), &objIsEcmaObject, &objNotEcmaObject);
2742 builder_.Bind(&objNotEcmaObject);
2743 {
2744 result = builder_.TaggedFalse();
2745 builder_.Jump(&exit);
2746 }
2747 builder_.Bind(&objIsEcmaObject);
2748 {
2749 // 4. Let P be Get(C, "prototype").
2750 Label getCtorProtoSlowPath(&builder_);
2751 Label ctorIsJSFunction(&builder_);
2752 Label gotCtorPrototype(&builder_);
2753 Label isHeapObject(&builder_);
2754 DEFVALUE(constructorPrototype, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
2755 BRANCH_CIR(builder_.IsJSFunction(glue, target), &ctorIsJSFunction, &getCtorProtoSlowPath);
2756 builder_.Bind(&ctorIsJSFunction);
2757 {
2758 Label getCtorProtoFastPath(&builder_);
2759 GateRef ctorProtoOrHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), target,
2760 JSFunction::PROTO_OR_DYNCLASS_OFFSET);
2761
2762 BRANCH_CIR(builder_.TaggedIsHole(ctorProtoOrHC), &getCtorProtoSlowPath, &getCtorProtoFastPath);
2763 builder_.Bind(&getCtorProtoFastPath);
2764 {
2765 Label isHClass(&builder_);
2766 Label isPrototype(&builder_);
2767 BRANCH_CIR(builder_.TaggedIsHeapObject(ctorProtoOrHC, compilationEnv_),
2768 &isHeapObject, &getCtorProtoSlowPath);
2769 builder_.Bind(&isHeapObject);
2770 BRANCH_CIR(builder_.IsJSHClass(glue, ctorProtoOrHC), &isHClass, &isPrototype);
2771 builder_.Bind(&isHClass);
2772 {
2773 constructorPrototype = builder_.LoadPrototype(glue_, ctorProtoOrHC);
2774 builder_.Jump(&gotCtorPrototype);
2775 }
2776 builder_.Bind(&isPrototype);
2777 {
2778 constructorPrototype = ctorProtoOrHC;
2779 builder_.Jump(&gotCtorPrototype);
2780 }
2781 }
2782 }
2783 builder_.Bind(&getCtorProtoSlowPath);
2784 {
2785 auto prototypeString = builder_.GetGlobalConstantValue(ConstantIndex::PROTOTYPE_STRING_INDEX);
2786 constructorPrototype = builder_.CallRuntime(glue, RTSTUB_ID(GetPropertyByName), Gate::InvalidGateRef,
2787 { target, prototypeString }, gate);
2788 builder_.Jump(&gotCtorPrototype);
2789 }
2790 // 6. If Type(P) is not Object, throw a TypeError exception.
2791 Label prototypeIsEcmaObj(&builder_);
2792 Label prototypeNotEcmaObj(&builder_);
2793 builder_.Bind(&gotCtorPrototype);
2794 {
2795 BRANCH_CIR(builder_.IsEcmaObject(glue, *constructorPrototype), &prototypeIsEcmaObj, &prototypeNotEcmaObj);
2796 builder_.Bind(&prototypeNotEcmaObj);
2797 {
2798 GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
2799 builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
2800 { builder_.Int32ToTaggedInt(taggedId) }, gate);
2801 result = builder_.ExceptionConstant();
2802 builder_.Jump(&exit);
2803 }
2804 }
2805 builder_.Bind(&prototypeIsEcmaObj);
2806 // 7. Repeat
2807 // a.Let O be O.[[GetPrototypeOf]]().
2808 // b.ReturnIfAbrupt(O).
2809 // c.If O is null, return false.
2810 // d.If SameValue(P, O) is true, return true.
2811 Label loopHead(&builder_);
2812 Label loopEnd(&builder_);
2813 Label afterLoop(&builder_);
2814 Label strictEqual1(&builder_);
2815 Label notStrictEqual1(&builder_);
2816 Label shouldReturn(&builder_);
2817 Label shouldContinue(&builder_);
2818
2819 BRANCH_CIR(builder_.TaggedIsNull(*object), &afterLoop, &loopHead);
2820 builder_.LoopBegin(&loopHead);
2821 {
2822 GateRef isEqual = builder_.Equal(*object, *constructorPrototype);
2823
2824 BRANCH_CIR(isEqual, &strictEqual1, ¬StrictEqual1);
2825 builder_.Bind(&strictEqual1);
2826 {
2827 result = builder_.TaggedTrue();
2828 builder_.Jump(&exit);
2829 }
2830 builder_.Bind(¬StrictEqual1);
2831 {
2832 Label objectIsHeapObject(&builder_);
2833 Label objectIsEcmaObject(&builder_);
2834 Label objectNotEcmaObject(&builder_);
2835
2836 BRANCH_CIR(builder_.TaggedIsHeapObject(*object, compilationEnv_),
2837 &objectIsHeapObject, &objectNotEcmaObject);
2838 builder_.Bind(&objectIsHeapObject);
2839 BRANCH_CIR(builder_.TaggedObjectIsEcmaObject(glue, *object), &objectIsEcmaObject, &objectNotEcmaObject);
2840 builder_.Bind(&objectNotEcmaObject);
2841 {
2842 GateRef taggedId = builder_.Int32(GET_MESSAGE_STRING_ID(CanNotGetNotEcmaObject));
2843 builder_.CallRuntime(glue, RTSTUB_ID(ThrowTypeError), Gate::InvalidGateRef,
2844 { builder_.Int32ToTaggedInt(taggedId) }, gate);
2845 result = builder_.ExceptionConstant();
2846 builder_.Jump(&exit);
2847 }
2848 builder_.Bind(&objectIsEcmaObject);
2849 {
2850 Label objectIsJsProxy(&builder_);
2851 Label objectNotIsJsProxy(&builder_);
2852 BRANCH_CIR(builder_.IsJsProxy(glue, *object), &objectIsJsProxy, &objectNotIsJsProxy);
2853 builder_.Bind(&objectIsJsProxy);
2854 {
2855 object = builder_.CallRuntime(glue, RTSTUB_ID(CallGetPrototype), Gate::InvalidGateRef,
2856 { *object }, gate);
2857 builder_.Jump(&shouldContinue);
2858 }
2859 builder_.Bind(&objectNotIsJsProxy);
2860 {
2861 GateRef objHClass = builder_.LoadHClassByConstOffset(glue, *object);
2862 object = builder_.LoadPrototype(glue_, objHClass);
2863 builder_.Jump(&shouldContinue);
2864 }
2865 }
2866 }
2867 builder_.Bind(&shouldContinue);
2868 BRANCH_CIR(builder_.TaggedIsNull(*object), &afterLoop, &loopEnd);
2869 }
2870 builder_.Bind(&loopEnd);
2871 builder_.LoopEnd(&loopHead);
2872 builder_.Bind(&afterLoop);
2873 {
2874 result = builder_.TaggedFalse();
2875 builder_.Jump(&exit);
2876 }
2877 }
2878 builder_.Bind(&exit);
2879 ReplaceGateWithPendingException(glue, gate, builder_.GetState(), builder_.GetDepend(), *result);
2880 }
2881
LowerProtoChangeMarkerCheck(GateRef glue,GateRef gate)2882 void TypedHCRLowering::LowerProtoChangeMarkerCheck(GateRef glue, GateRef gate)
2883 {
2884 Environment env(gate, circuit_, &builder_);
2885 GateRef frameState = acc_.GetFrameState(gate);
2886 GateRef receiver = acc_.GetValueIn(gate, 0);
2887 auto hclass = builder_.LoadHClassByConstOffset(glue, receiver);
2888 auto prototype = builder_.LoadPrototype(glue_, hclass);
2889 auto protoHClass = builder_.LoadHClassByConstOffset(glue, prototype);
2890 auto marker = builder_.LoadProtoChangeMarker(glue_, protoHClass);
2891 auto notNull = builder_.TaggedIsNotNull(marker);
2892 builder_.DeoptCheck(notNull, frameState, DeoptType::PROTOTYPECHANGED2);
2893 auto hasChanged = builder_.GetHasChanged(marker);
2894 builder_.DeoptCheck(builder_.BoolNot(hasChanged), frameState, DeoptType::PROTOTYPECHANGED2);
2895 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2896 }
2897
LowerPrimitiveTypeProtoChangeMarkerCheck(GateRef glue,GateRef gate)2898 void TypedHCRLowering::LowerPrimitiveTypeProtoChangeMarkerCheck(GateRef glue, GateRef gate)
2899 {
2900 Environment env(gate, circuit_, &builder_);
2901 GateRef frameState = acc_.GetFrameState(gate);
2902 GateRef prototype = acc_.GetValueIn(gate, 0);
2903 auto protoHClass = builder_.LoadHClassByConstOffset(glue, prototype);
2904 auto marker = builder_.LoadProtoChangeMarker(glue_, protoHClass);
2905 auto notNull = builder_.TaggedIsNotNull(marker);
2906 builder_.DeoptCheck(notNull, frameState, DeoptType::PRIMTYPEPROTOTYPECHANGED);
2907 auto hasChanged = builder_.GetHasChanged(marker);
2908 builder_.DeoptCheck(builder_.BoolNot(hasChanged), frameState, DeoptType::PRIMTYPEPROTOTYPECHANGED);
2909 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
2910 }
2911
LowerMonoLoadPropertyOnProto(GateRef glue,GateRef gate)2912 void TypedHCRLowering::LowerMonoLoadPropertyOnProto(GateRef glue, GateRef gate)
2913 {
2914 Environment env(gate, circuit_, &builder_);
2915 GateRef frameState = acc_.GetFrameState(gate);
2916 GateRef receiver = acc_.GetValueIn(gate, 0);
2917 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
2918 GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
2919 GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constPool
2920 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
2921 GateRef result = Circuit::NullGate();
2922 ASSERT(plr.IsLocal() || plr.IsFunction());
2923
2924 Label loadHolder(&builder_);
2925 DEFVALUE(current, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
2926 GetPropertyHolderFromProtoChain(glue, { receiver, hclassIndex, unsharedConstPool, frameState },
2927 &loadHolder, ¤t, DeoptType::INCONSISTENTHCLASS8);
2928 builder_.Bind(&loadHolder);
2929 result = LoadPropertyFromHolder(*current, plr);
2930 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
2931 }
2932
GetPropertyHolderFromProtoChain(GateRef glue,ProtoTypeHolderInfo holderInfo,Label * loadHolder,Variable * current,DeoptType deoptType)2933 void TypedHCRLowering::GetPropertyHolderFromProtoChain(
2934 GateRef glue, ProtoTypeHolderInfo holderInfo, Label *loadHolder, Variable *current, DeoptType deoptType)
2935 {
2936 if (compilationEnv_->SupportHeapConstant()) {
2937 auto *jitCompilationEnv = static_cast<JitCompilationEnv*>(compilationEnv_);
2938 const auto &holderHClassIndex2HeapConstantIndex = jitCompilationEnv->GetHolderHClassIndex2HeapConstantIndex();
2939 auto holderHClassIndex = acc_.GetConstantValue(holderInfo.holderHClassIndex);
2940 auto itr = holderHClassIndex2HeapConstantIndex.find(holderHClassIndex);
2941 if (itr != holderHClassIndex2HeapConstantIndex.end()) {
2942 *current = builder_.HeapConstant(itr->second);
2943 builder_.Jump(loadHolder);
2944 return;
2945 }
2946 }
2947 auto receiverHC = builder_.LoadHClassByConstOffset(glue, holderInfo.receiver);
2948 *current = builder_.LoadPrototype(glue_, receiverHC);
2949
2950 // lookup from receiver for holder
2951 auto holderHC = builder_.LoadHClassFromConstpool(
2952 holderInfo.unsharedConstPool, acc_.GetConstantValue(holderInfo.holderHClassIndex));
2953 Label loopHead(&builder_);
2954 Label lookUpProto(&builder_);
2955 builder_.Jump(&loopHead);
2956
2957 builder_.LoopBegin(&loopHead);
2958 builder_.DeoptCheck(builder_.TaggedIsNotNull(current->ReadVariable()), holderInfo.frameState, deoptType);
2959 auto curHC = builder_.LoadHClassByConstOffset(glue, current->ReadVariable());
2960 BRANCH_CIR(builder_.Equal(curHC, holderHC), loadHolder, &lookUpProto);
2961
2962 builder_.Bind(&lookUpProto);
2963 *current = builder_.LoadPrototype(glue_, curHC);
2964 builder_.LoopEnd(&loopHead);
2965 }
2966
LowerMonoCallGetterOnProto(GateRef gate,GateRef glue)2967 void TypedHCRLowering::LowerMonoCallGetterOnProto(GateRef gate, GateRef glue)
2968 {
2969 Environment env(gate, circuit_, &builder_);
2970 GateRef frameState = acc_.GetFrameState(gate);
2971 GateRef receiver = acc_.GetValueIn(gate, 0);
2972 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
2973 GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
2974 GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constPool
2975 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
2976 GateRef accessor = Circuit::NullGate();
2977 GateRef holder = Circuit::NullGate();
2978
2979 Label loadHolder(&builder_);
2980 DEFVALUE(current, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
2981 GetPropertyHolderFromProtoChain(glue, { receiver, hclassIndex, unsharedConstPool, frameState },
2982 &loadHolder, ¤t, DeoptType::INCONSISTENTHCLASS9);
2983
2984 builder_.Bind(&loadHolder);
2985 holder = *current;
2986 accessor = LoadPropertyFromHolder(holder, plr);
2987 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
2988 Label isInternalAccessor(&builder_);
2989 Label notInternalAccessor(&builder_);
2990 Label callGetter(&builder_);
2991 Label exit(&builder_);
2992 BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, ¬InternalAccessor);
2993 {
2994 builder_.Bind(&isInternalAccessor);
2995 {
2996 result = builder_.CallRuntime(glue, RTSTUB_ID(CallInternalGetter),
2997 Gate::InvalidGateRef, { accessor, holder }, gate);
2998 builder_.Jump(&exit);
2999 }
3000 builder_.Bind(¬InternalAccessor);
3001 {
3002 GateRef getter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::GETTER_OFFSET);
3003 BRANCH_CIR(builder_.IsSpecial(getter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callGetter);
3004 builder_.Bind(&callGetter);
3005 {
3006 result = CallAccessor(glue, gate, getter, receiver, AccessorMode::GETTER);
3007 builder_.Jump(&exit);
3008 }
3009 }
3010 }
3011 builder_.Bind(&exit);
3012 ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
3013 }
3014
LoadPropertyFromHolder(GateRef holder,PropertyLookupResult plr)3015 GateRef TypedHCRLowering::LoadPropertyFromHolder(GateRef holder, PropertyLookupResult plr)
3016 {
3017 GateRef result = Circuit::NullGate();
3018 GateRef glue = glue_;
3019 // while loading from iterator result, it may be the case that traversing an array including holes using 'for of',
3020 // need to convert hole to undefined
3021 if (plr.IsNotHole() || (compilationEnv_->IsJitCompiler() && !plr.IsLoadFromIterResult())) {
3022 ASSERT(plr.IsLocal());
3023 if (plr.IsInlinedProps()) {
3024 result = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
3025 } else {
3026 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
3027 result = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
3028 }
3029 } else if (plr.IsLocal()) {
3030 if (plr.IsInlinedProps()) {
3031 result = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
3032 } else {
3033 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
3034 result = builder_.GetValueFromTaggedArray(glue, properties, builder_.Int32(plr.GetOffset()));
3035 }
3036 result = builder_.ConvertHoleAsUndefined(result);
3037 } else {
3038 UNREACHABLE();
3039 }
3040 return result;
3041 }
3042
LowerMonoStorePropertyLookUpProto(GateRef gate,GateRef glue)3043 void TypedHCRLowering::LowerMonoStorePropertyLookUpProto(GateRef gate, GateRef glue)
3044 {
3045 Environment env(gate, circuit_, &builder_);
3046 GateRef frameState = acc_.GetFrameState(gate);
3047 GateRef receiver = acc_.GetValueIn(gate, 0);
3048 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
3049 GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
3050 GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constpool
3051 GateRef value = acc_.GetValueIn(gate, 4); // 4: value
3052 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
3053 bool noBarrier = acc_.IsNoBarrier(gate);
3054
3055 Label loadHolder(&builder_);
3056 DEFVALUE(current, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
3057 GetPropertyHolderFromProtoChain(glue, { receiver, hclassIndex, unsharedConstPool, frameState },
3058 &loadHolder, ¤t, DeoptType::INCONSISTENTHCLASS10);
3059 builder_.Bind(&loadHolder);
3060 Label exit(&builder_);
3061
3062 builder_.Bind(&loadHolder);
3063 if (!plr.IsAccessor()) {
3064 StorePropertyOnHolder(*current, value, plr, noBarrier);
3065 builder_.Jump(&exit);
3066 } else {
3067 GateRef accessor = LoadPropertyFromHolder(*current, plr);
3068 Label isInternalAccessor(&builder_);
3069 Label notInternalAccessor(&builder_);
3070 Label callSetter(&builder_);
3071 BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, ¬InternalAccessor);
3072 {
3073 builder_.Bind(&isInternalAccessor);
3074 {
3075 builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
3076 Gate::InvalidGateRef, { receiver, accessor, value }, gate);
3077 builder_.Jump(&exit);
3078 }
3079 builder_.Bind(¬InternalAccessor);
3080 {
3081 GateRef setter =
3082 builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
3083 BRANCH_CIR(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
3084 builder_.Bind(&callSetter);
3085 {
3086 CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
3087 builder_.Jump(&exit);
3088 }
3089 }
3090 }
3091 }
3092 builder_.Bind(&exit);
3093 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3094 }
3095
LowerMonoStoreProperty(GateRef gate,GateRef glue)3096 void TypedHCRLowering::LowerMonoStoreProperty(GateRef gate, GateRef glue)
3097 {
3098 Environment env(gate, circuit_, &builder_);
3099 GateRef frameState = acc_.GetFrameState(gate);
3100 GateRef receiver = acc_.GetValueIn(gate, 0);
3101 GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
3102 GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
3103 GateRef unsharedConstPool = acc_.GetValueIn(gate, 3); // 3: constPool
3104 GateRef value = acc_.GetValueIn(gate, 4); // 4: value
3105 GateRef keyIndex = acc_.GetValueIn(gate, 5); // 5: keyIndex
3106 bool isPrototype = acc_.TryGetValue(acc_.GetValueIn(gate, 6)); // 6: proto flag Index
3107 PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
3108 bool noBarrier = acc_.IsNoBarrier(gate);
3109 auto receiverHC = builder_.LoadHClassByConstOffset(glue, receiver);
3110 // transition happened
3111 Label exit(&builder_);
3112 Label notProto(&builder_);
3113 Label isProto(&builder_);
3114 auto newHolderHC = builder_.LoadHClassFromConstpool(unsharedConstPool, acc_.GetConstantValue(hclassIndex));
3115 if (compilationEnv_->IsAotCompiler()) {
3116 auto prototype = builder_.LoadPrototype(glue_, receiverHC);
3117 builder_.StorePrototype(glue_, newHolderHC, prototype);
3118 }
3119 if (isPrototype) {
3120 builder_.Branch(builder_.IsPrototypeHClass(receiverHC), &isProto, ¬Proto,
3121 BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT, "isPrototypeHClass");
3122 builder_.Bind(&isProto);
3123
3124 uint32_t heapConstantIndex = JitCompilationEnv::INVALID_HEAP_CONSTANT_INDEX;
3125 GateRef propKey = 0;
3126 if (compilationEnv_->SupportHeapConstant()) {
3127 auto *jitCompilationEnv = static_cast<JitCompilationEnv*>(compilationEnv_);
3128 const auto &gate2HeapConstantIndex = jitCompilationEnv->GetGate2HeapConstantIndex();
3129 auto itr = gate2HeapConstantIndex.find(gate);
3130 if (itr != gate2HeapConstantIndex.end()) {
3131 heapConstantIndex = itr->second;
3132 propKey = builder_.HeapConstant(heapConstantIndex);
3133 }
3134 }
3135 if (heapConstantIndex == JitCompilationEnv::INVALID_HEAP_CONSTANT_INDEX) {
3136 propKey = builder_.GetObjectByIndexFromConstPool(glue, gate, frameState, keyIndex, ConstPoolType::STRING);
3137 }
3138 builder_.CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef,
3139 { receiverHC, newHolderHC, propKey }, gate);
3140 builder_.Jump(¬Proto);
3141 builder_.Bind(¬Proto);
3142 }
3143 MemoryAttribute mAttr = MemoryAttribute::NeedBarrierAndAtomic();
3144 builder_.TransitionHClass(glue, receiver, newHolderHC, mAttr);
3145 if (!plr.IsInlinedProps()) {
3146 auto properties =
3147 builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
3148 auto capacity = builder_.LoadConstOffset(VariableType::INT32(), properties, TaggedArray::LENGTH_OFFSET);
3149 auto index = builder_.Int32(plr.GetOffset());
3150 Label needExtend(&builder_);
3151 Label notExtend(&builder_);
3152 BRANCH_CIR(builder_.Int32UnsignedLessThan(index, capacity), ¬Extend, &needExtend);
3153 builder_.Bind(¬Extend);
3154 {
3155 if (!plr.IsAccessor()) {
3156 StorePropertyOnHolder(receiver, value, plr, noBarrier);
3157 builder_.Jump(&exit);
3158 } else {
3159 GateRef accessor = LoadPropertyFromHolder(receiver, plr);
3160 Label isInternalAccessor(&builder_);
3161 Label notInternalAccessor(&builder_);
3162 Label callSetter(&builder_);
3163 BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, ¬InternalAccessor);
3164 {
3165 builder_.Bind(&isInternalAccessor);
3166 {
3167 builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
3168 Gate::InvalidGateRef, { receiver, accessor, value }, gate);
3169 builder_.Jump(&exit);
3170 }
3171 builder_.Bind(¬InternalAccessor);
3172 {
3173 GateRef setter =
3174 builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
3175 BRANCH_CIR(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
3176 builder_.Bind(&callSetter);
3177 {
3178 CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
3179 builder_.Jump(&exit);
3180 }
3181 }
3182 }
3183 }
3184 }
3185 builder_.Bind(&needExtend);
3186 {
3187 builder_.CallRuntime(glue,
3188 RTSTUB_ID(PropertiesSetValue),
3189 Gate::InvalidGateRef,
3190 { receiver, value, properties, builder_.Int32ToTaggedInt(capacity),
3191 builder_.Int32ToTaggedInt(index) }, gate);
3192 builder_.Jump(&exit);
3193 }
3194 } else {
3195 if (!plr.IsAccessor()) {
3196 StorePropertyOnHolder(receiver, value, plr, noBarrier);
3197 builder_.Jump(&exit);
3198 } else {
3199 GateRef accessor = LoadPropertyFromHolder(receiver, plr);
3200 Label isInternalAccessor(&builder_);
3201 Label notInternalAccessor(&builder_);
3202 Label callSetter(&builder_);
3203 BRANCH_CIR(builder_.IsAccessorInternal(glue, accessor), &isInternalAccessor, ¬InternalAccessor);
3204 {
3205 builder_.Bind(&isInternalAccessor);
3206 {
3207 builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
3208 Gate::InvalidGateRef, { receiver, accessor, value }, gate);
3209 builder_.Jump(&exit);
3210 }
3211 builder_.Bind(¬InternalAccessor);
3212 {
3213 GateRef setter =
3214 builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
3215 BRANCH_CIR(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
3216 builder_.Bind(&callSetter);
3217 {
3218 CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
3219 builder_.Jump(&exit);
3220 }
3221 }
3222 }
3223 }
3224 }
3225 builder_.Bind(&exit);
3226 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3227 }
3228
StorePropertyOnHolder(GateRef holder,GateRef value,PropertyLookupResult plr,bool noBarrier)3229 void TypedHCRLowering::StorePropertyOnHolder(GateRef holder, GateRef value, PropertyLookupResult plr, bool noBarrier)
3230 {
3231 if (!noBarrier) {
3232 if (plr.IsInlinedProps()) {
3233 builder_.StoreConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset(), value);
3234 } else {
3235 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
3236 builder_.SetValueToTaggedArray(
3237 VariableType::JS_ANY(), glue_, properties, builder_.Int32(plr.GetOffset()), value);
3238 }
3239 } else {
3240 if (plr.IsInlinedProps()) {
3241 builder_.StoreConstOffset(GetVarType(plr), holder, plr.GetOffset(), value);
3242 } else {
3243 auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
3244 builder_.SetValueToTaggedArray(
3245 GetVarType(plr), glue_, properties, builder_.Int32(plr.GetOffset()), value);
3246 }
3247 }
3248 }
3249
GetOldObject(CompilationEnv * compilationEnv,CircuitBuilder & builder,const GateAccessor & acc,GateRef glue,GateRef gate)3250 static GateRef GetOldObject(CompilationEnv *compilationEnv, CircuitBuilder &builder,
3251 const GateAccessor &acc, GateRef glue, GateRef gate)
3252 {
3253 if (compilationEnv->SupportHeapConstant()) {
3254 auto *jitCompilationEnv = static_cast<JitCompilationEnv*>(compilationEnv);
3255 const auto &gate2HeapConstantIndex = jitCompilationEnv->GetGate2HeapConstantIndex();
3256 auto itr = gate2HeapConstantIndex.find(gate);
3257 // object must be found in unshared constpool,
3258 // which is ensured by TypedBytecodeLowering::LowerCreateObjectWithBuffer
3259 ASSERT(itr != gate2HeapConstantIndex.end());
3260 return builder.HeapConstant(itr->second);
3261 }
3262 GateRef frameState = acc.GetFrameState(gate);
3263 GateRef index = acc.GetValueIn(gate, 1); // 1: index
3264 return builder.GetObjectByIndexFromConstPool(
3265 glue, gate, frameState, builder.TruncInt64ToInt32(index), ConstPoolType::OBJECT_LITERAL);
3266 }
3267
LowerTypedCreateObjWithBuffer(GateRef gate,GateRef glue)3268 void TypedHCRLowering::LowerTypedCreateObjWithBuffer(GateRef gate, GateRef glue)
3269 {
3270 Environment env(gate, circuit_, &builder_);
3271 DEFVALUE(ret, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3272 Label equal(&builder_);
3273 Label notEqual(&builder_);
3274 Label exit(&builder_);
3275 GateRef objSize = acc_.GetValueIn(gate, 0); // 0: objSize
3276 GateRef lexEnv = acc_.GetValueIn(gate, 3); // 3: lexenv
3277 size_t numValueIn = acc_.GetNumValueIn(gate);
3278
3279 GateRef oldObj = GetOldObject(compilationEnv_, builder_, acc_, glue, gate);
3280 GateRef hclass = builder_.LoadHClassByConstOffset(glue, oldObj);
3281 GateRef emptyArray = builder_.GetGlobalConstantValue(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
3282 GateRef objectSize = builder_.GetObjectSizeFromHClass(hclass);
3283 BRANCH_CIR(builder_.Equal(objectSize, objSize), &equal, ¬Equal);
3284 builder_.Bind(&equal);
3285 {
3286 builder_.StartAllocate();
3287 GateRef newObj = builder_.HeapAlloc(glue, objSize, GateType::TaggedValue(), RegionSpaceFlag::IN_YOUNG_SPACE);
3288 builder_.StoreHClass(glue, newObj, hclass, MemoryAttribute::NeedBarrierAndAtomic());
3289 builder_.StoreConstOffset(VariableType::INT64(), newObj,
3290 JSObject::HASH_OFFSET, builder_.Int64(JSTaggedValue(0).GetRawData()));
3291 builder_.StoreConstOffset(VariableType::INT64(), newObj, JSObject::PROPERTIES_OFFSET, emptyArray);
3292 builder_.StoreConstOffset(VariableType::INT64(), newObj, JSObject::ELEMENTS_OFFSET, emptyArray);
3293 size_t fixedNumValueIn = 4; // objSize, index, hclass, lexEnv
3294 for (uint32_t i = 0; i < numValueIn - fixedNumValueIn; i += 2) { // 2 : value, offset
3295 builder_.StoreConstOffset(VariableType::INT64(), newObj,
3296 acc_.GetConstantValue(acc_.GetValueIn(gate, i + fixedNumValueIn + 1)),
3297 acc_.GetValueIn(gate, i + fixedNumValueIn));
3298 }
3299 ret = builder_.FinishAllocate(newObj);
3300 builder_.Jump(&exit);
3301 }
3302 builder_.Bind(¬Equal);
3303 {
3304 ret = builder_.CallRuntime(glue, RTSTUB_ID(CreateObjectHavingMethod),
3305 Gate::InvalidGateRef, { oldObj, lexEnv }, gate);
3306 builder_.Jump(&exit);
3307 }
3308 builder_.Bind(&exit);
3309 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *ret);
3310 }
3311
LowerStringFromSingleCharCode(GateRef gate,GateRef glue)3312 void TypedHCRLowering::LowerStringFromSingleCharCode(GateRef gate, GateRef glue)
3313 {
3314 Environment env(gate, circuit_, &builder_);
3315 DEFVALUE(value, (&builder_), VariableType::INT16(), builder_.Int16(0));
3316 DEFVALUE(res, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3317 Label isPendingException(&builder_);
3318 Label noPendingException(&builder_);
3319 Label exit(&builder_);
3320 Label isInt(&builder_);
3321 Label notInt(&builder_);
3322 Label newObj(&builder_);
3323 Label canBeCompress(&builder_);
3324 Label canNotBeCompress(&builder_);
3325 GateRef codePointTag = acc_.GetValueIn(gate);
3326 GateRef codePointValue = builder_.ToNumber(gate, codePointTag, glue);
3327 BRANCH_CIR(builder_.HasPendingException(glue, compilationEnv_), &isPendingException, &noPendingException);
3328 builder_.Bind(&isPendingException);
3329 {
3330 res = builder_.ExceptionConstant();
3331 builder_.Jump(&exit);
3332 }
3333 builder_.Bind(&noPendingException);
3334 {
3335 BRANCH_CIR(builder_.TaggedIsInt(codePointValue), &isInt, ¬Int);
3336 builder_.Bind(&isInt);
3337 {
3338 value = builder_.TruncInt32ToInt16(builder_.GetInt32OfTInt(codePointValue));
3339 builder_.Jump(&newObj);
3340 }
3341 builder_.Bind(¬Int);
3342 {
3343 value = builder_.TruncInt32ToInt16(
3344 builder_.TruncDoubleToInt(glue, builder_.GetDoubleOfTDouble(codePointValue), base::INT16_BITS));
3345 builder_.Jump(&newObj);
3346 }
3347 builder_.Bind(&newObj);
3348 BRANCH_CIR(builder_.IsASCIICharacter(builder_.ZExtInt16ToInt32(*value)), &canBeCompress, &canNotBeCompress);
3349 NewObjectStubBuilder newBuilder(&env);
3350 newBuilder.SetParameters(glue, 0);
3351 builder_.Bind(&canBeCompress);
3352 {
3353 GateRef singleCharTable = builder_.GetGlobalConstantValue(ConstantIndex::SINGLE_CHAR_TABLE_INDEX);
3354 res = builder_.GetValueFromTaggedArray(glue, singleCharTable, builder_.ZExtInt16ToInt32(*value));
3355 builder_.Jump(&exit);
3356 }
3357 builder_.Bind(&canNotBeCompress);
3358 {
3359 Label afterNew1(&builder_);
3360 newBuilder.AllocLineStringObject(&res, &afterNew1, builder_.Int32(1), false);
3361 builder_.Bind(&afterNew1);
3362 {
3363 GateRef dst = builder_.ChangeTaggedPointerToInt64(
3364 builder_.PtrAdd(*res, builder_.IntPtr(LineString::DATA_OFFSET)));
3365 builder_.Store(VariableType::INT16(), glue, dst, builder_.IntPtr(0), *value);
3366 builder_.Jump(&exit);
3367 }
3368 }
3369 }
3370 builder_.Bind(&exit);
3371 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *res);
3372 }
3373
LowerMigrateArrayWithKind(GateRef gate,GateRef glue)3374 void TypedHCRLowering::LowerMigrateArrayWithKind(GateRef gate, GateRef glue)
3375 {
3376 Environment env(gate, circuit_, &builder_);
3377 Label exit(&builder_);
3378 GateRef object = acc_.GetValueIn(gate, 0);
3379 GateRef oldKind = acc_.GetValueIn(gate, 1); // 1: objSize
3380 GateRef newKind = acc_.GetValueIn(gate, 2); // 2: index
3381
3382 DEFVALUE(newElements, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3383 Label doMigration(&builder_);
3384 Label migrateFromInt(&builder_);
3385 Label migrateOtherKinds(&builder_);
3386 GateRef noNeedMigration = LogicOrBuilder(&env)
3387 .Or(builder_.Int32Equal(oldKind, newKind))
3388 .Or(builder_.BitAnd(builder_.Int32Equal(oldKind, builder_.Int32(Elements::ToUint(ElementsKind::INT))),
3389 builder_.Int32Equal(newKind, builder_.Int32(Elements::ToUint(ElementsKind::HOLE_INT)))))
3390 .Or(builder_.BitAnd(builder_.Int32Equal(oldKind, builder_.Int32(Elements::ToUint(ElementsKind::NUMBER))),
3391 builder_.Int32Equal(newKind, builder_.Int32(Elements::ToUint(ElementsKind::HOLE_NUMBER)))))
3392 .Done();
3393 BRANCH_CIR(noNeedMigration, &exit, &doMigration);
3394 builder_.Bind(&doMigration);
3395
3396 GateRef needCOW = builder_.IsJsCOWArray(glue, object, compilationEnv_);
3397 BRANCH_CIR(builder_.ElementsKindIsIntOrHoleInt(oldKind), &migrateFromInt, &migrateOtherKinds);
3398 builder_.Bind(&migrateFromInt);
3399 {
3400 Label migrateToHeapValuesFromInt(&builder_);
3401 Label migrateToRawValuesFromInt(&builder_);
3402 Label migrateToNumbersFromInt(&builder_);
3403 BRANCH_CIR(builder_.ElementsKindIsHeapKind(newKind),
3404 &migrateToHeapValuesFromInt, &migrateToRawValuesFromInt);
3405 builder_.Bind(&migrateToHeapValuesFromInt);
3406 {
3407 newElements = builder_.MigrateFromRawValueToHeapValues(object, needCOW, builder_.True());
3408 builder_.StoreConstOffset(VariableType::JS_ANY(), object, JSObject::ELEMENTS_OFFSET, *newElements);
3409 builder_.Jump(&exit);
3410 }
3411 builder_.Bind(&migrateToRawValuesFromInt);
3412 {
3413 BRANCH_CIR(builder_.ElementsKindIsNumOrHoleNum(newKind), &migrateToNumbersFromInt, &exit);
3414 builder_.Bind(&migrateToNumbersFromInt);
3415 {
3416 builder_.MigrateFromHoleIntToHoleNumber(object);
3417 builder_.Jump(&exit);
3418 }
3419 }
3420 }
3421 builder_.Bind(&migrateOtherKinds);
3422 {
3423 Label migrateFromNumber(&builder_);
3424 Label migrateToHeapValuesFromNum(&builder_);
3425 Label migrateToRawValuesFromNum(&builder_);
3426 Label migrateToIntFromNum(&builder_);
3427 Label migrateToRawValueFromTagged(&builder_);
3428 BRANCH_CIR(builder_.ElementsKindIsNumOrHoleNum(oldKind), &migrateFromNumber, &migrateToRawValueFromTagged);
3429 builder_.Bind(&migrateFromNumber);
3430 {
3431 BRANCH_CIR(builder_.ElementsKindIsHeapKind(newKind),
3432 &migrateToHeapValuesFromNum, &migrateToRawValuesFromNum);
3433 builder_.Bind(&migrateToHeapValuesFromNum);
3434 {
3435 Label migrateToTaggedFromNum(&builder_);
3436 BRANCH_CIR(builder_.ElementsKindIsHeapKind(newKind), &migrateToTaggedFromNum, &exit);
3437 builder_.Bind(&migrateToTaggedFromNum);
3438 {
3439 newElements = builder_.MigrateFromRawValueToHeapValues(object, needCOW, builder_.False());
3440 builder_.StoreConstOffset(VariableType::JS_ANY(), object, JSObject::ELEMENTS_OFFSET, *newElements);
3441 builder_.Jump(&exit);
3442 }
3443 }
3444 builder_.Bind(&migrateToRawValuesFromNum);
3445 {
3446 BRANCH_CIR(builder_.ElementsKindIsIntOrHoleInt(newKind), &migrateToIntFromNum, &exit);
3447 builder_.Bind(&migrateToIntFromNum);
3448 {
3449 builder_.MigrateFromHoleNumberToHoleInt(object);
3450 builder_.Jump(&exit);
3451 }
3452 }
3453 }
3454 builder_.Bind(&migrateToRawValueFromTagged);
3455 {
3456 Label migrateToIntFromTagged(&builder_);
3457 Label migrateToOthersFromTagged(&builder_);
3458 BRANCH_CIR(builder_.ElementsKindIsIntOrHoleInt(newKind),
3459 &migrateToIntFromTagged, &migrateToOthersFromTagged);
3460 builder_.Bind(&migrateToIntFromTagged);
3461 {
3462 newElements = builder_.MigrateFromHeapValueToRawValue(object, needCOW, builder_.True());
3463 builder_.StoreConstOffset(VariableType::JS_ANY(), object, JSObject::ELEMENTS_OFFSET, *newElements);
3464 builder_.Jump(&exit);
3465 }
3466 builder_.Bind(&migrateToOthersFromTagged);
3467 {
3468 Label migrateToNumFromTagged(&builder_);
3469 BRANCH_CIR(builder_.ElementsKindIsNumOrHoleNum(newKind), &migrateToNumFromTagged, &exit);
3470 builder_.Bind(&migrateToNumFromTagged);
3471 {
3472 newElements = builder_.MigrateFromHeapValueToRawValue(object, needCOW, builder_.False());
3473 builder_.StoreConstOffset(VariableType::JS_ANY(), object, JSObject::ELEMENTS_OFFSET, *newElements);
3474 builder_.Jump(&exit);
3475 }
3476 }
3477 }
3478 }
3479 builder_.Bind(&exit);
3480 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3481 }
3482
LowerNumberToString(GateRef gate,GateRef glue)3483 void TypedHCRLowering::LowerNumberToString(GateRef gate, GateRef glue)
3484 {
3485 Environment env(gate, circuit_, &builder_);
3486 DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.Undefined());
3487 GateRef number = acc_.GetValueIn(gate, 0);
3488 result = builder_.CallRuntime(glue, RTSTUB_ID(NumberToString),
3489 Gate::InvalidGateRef, { number }, gate);
3490 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
3491 }
3492
LowerEcmaObjectCheck(GateRef gate)3493 void TypedHCRLowering::LowerEcmaObjectCheck(GateRef gate)
3494 {
3495 Environment env(gate, circuit_, &builder_);
3496 GateRef value = acc_.GetValueIn(gate, 0);
3497 GateRef frameState = acc_.GetFrameState(gate);
3498 builder_.HeapObjectCheck(value, frameState);
3499 builder_.HeapObjectIsEcmaObjectCheck(value, frameState);
3500 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3501 }
3502
LowerElementskindCheck(GateRef glue,GateRef gate)3503 void TypedHCRLowering::LowerElementskindCheck(GateRef glue, GateRef gate)
3504 {
3505 Environment env(gate, circuit_, &builder_);
3506 GateRef frameState = acc_.GetFrameState(gate);
3507 ArrayMetaDataAccessor accessor = acc_.GetArrayMetaDataAccessor(gate);
3508 ElementsKind kind = accessor.GetElementsKind();
3509 GateRef check = Circuit::NullGate();
3510 GateRef receiver = acc_.GetValueIn(gate, 0);
3511 GateRef hclass = builder_.LoadHClassByConstOffset(glue, receiver);
3512
3513 if (Elements::IsComplex(kind)) {
3514 check = builder_.Int32GreaterThanOrEqual(builder_.Int32(Elements::ToUint(kind)),
3515 builder_.GetElementsKindByHClass(hclass));
3516 } else {
3517 check = builder_.Equal(builder_.Int32(Elements::ToUint(kind)), builder_.GetElementsKindByHClass(hclass));
3518 }
3519 builder_.DeoptCheck(check, frameState, DeoptType::INCONSISTENTELEMENTSKIND);
3520 acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
3521 }
3522
LowerCheckConstructor(GateRef gate,GateRef glue)3523 void TypedHCRLowering::LowerCheckConstructor(GateRef gate, GateRef glue)
3524 {
3525 Environment env(gate, circuit_, &builder_);
3526 NewObjectStubBuilder objBuilder(&env);
3527 GateRef superFunc = acc_.GetValueIn(gate, 0); // 0 : Super func
3528 GateRef ctorResult = acc_.GetValueIn(gate, 1); // 1: Constructor result
3529 GateRef thisObj = acc_.GetValueIn(gate, 2); // 2: This object
3530 GateRef result = objBuilder.ConstructorCheck(glue, superFunc, ctorResult, thisObj);
3531 ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), result);
3532 }
3533 } // namespace panda::ecmascript::kungfu
3534