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