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