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