2021-09-04 08:06:49 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2022-07-25 01:53:14 +00:00
|
|
|
#include "ecmascript/compiler/stub_builder-inl.h"
|
2022-07-23 10:33:33 +00:00
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
#include "ecmascript/compiler/llvm_ir_builder.h"
|
2022-07-23 10:33:33 +00:00
|
|
|
#include "ecmascript/compiler/rt_call_signature.h"
|
2022-07-23 07:52:48 +00:00
|
|
|
#include "ecmascript/js_api/js_api_arraylist.h"
|
|
|
|
#include "ecmascript/js_api/js_api_vector.h"
|
2021-09-04 08:06:49 +00:00
|
|
|
#include "ecmascript/js_object.h"
|
2022-04-16 10:04:54 +00:00
|
|
|
#include "ecmascript/mem/remembered_set.h"
|
2022-02-07 09:23:03 +00:00
|
|
|
#include "ecmascript/message_string.h"
|
2022-03-16 10:12:15 +00:00
|
|
|
#include "ecmascript/tagged_dictionary.h"
|
2022-04-25 02:15:36 +00:00
|
|
|
#include "ecmascript/tagged_hash_table.h"
|
2021-09-04 08:06:49 +00:00
|
|
|
|
2021-12-23 06:55:22 +00:00
|
|
|
namespace panda::ecmascript::kungfu {
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::Jump(Label *label)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
ASSERT(label);
|
2022-07-25 01:53:14 +00:00
|
|
|
auto currentLabel = env_->GetCurrentLabel();
|
2021-09-04 08:06:49 +00:00
|
|
|
auto currentControl = currentLabel->GetControl();
|
2022-07-25 01:53:14 +00:00
|
|
|
auto jump = env_->GetBuilder()->Goto(currentControl);
|
2021-09-04 08:06:49 +00:00
|
|
|
currentLabel->SetControl(jump);
|
|
|
|
label->AppendPredecessor(currentLabel);
|
|
|
|
label->MergeControl(currentLabel->GetControl());
|
2022-07-25 01:53:14 +00:00
|
|
|
env_->SetCurrentLabel(nullptr);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::Branch(GateRef condition, Label *trueLabel, Label *falseLabel)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-07-25 01:53:14 +00:00
|
|
|
auto currentLabel = env_->GetCurrentLabel();
|
2021-09-04 08:06:49 +00:00
|
|
|
auto currentControl = currentLabel->GetControl();
|
2022-07-25 01:53:14 +00:00
|
|
|
GateRef ifBranch = env_->GetBuilder()->Branch(currentControl, condition);
|
2021-09-04 08:06:49 +00:00
|
|
|
currentLabel->SetControl(ifBranch);
|
2022-07-25 01:53:14 +00:00
|
|
|
GateRef ifTrue = env_->GetBuilder()->IfTrue(ifBranch);
|
|
|
|
trueLabel->AppendPredecessor(env_->GetCurrentLabel());
|
2021-09-04 08:06:49 +00:00
|
|
|
trueLabel->MergeControl(ifTrue);
|
2022-07-25 01:53:14 +00:00
|
|
|
GateRef ifFalse = env_->GetBuilder()->IfFalse(ifBranch);
|
|
|
|
falseLabel->AppendPredecessor(env_->GetCurrentLabel());
|
2021-09-04 08:06:49 +00:00
|
|
|
falseLabel->MergeControl(ifFalse);
|
2022-07-25 01:53:14 +00:00
|
|
|
env_->SetCurrentLabel(nullptr);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-07-25 01:53:14 +00:00
|
|
|
auto currentLabel = env_->GetCurrentLabel();
|
2021-09-04 08:06:49 +00:00
|
|
|
auto currentControl = currentLabel->GetControl();
|
2022-07-25 01:53:14 +00:00
|
|
|
GateRef switchBranch = env_->GetBuilder()->SwitchBranch(currentControl, index, numberOfKeys);
|
2021-09-04 08:06:49 +00:00
|
|
|
currentLabel->SetControl(switchBranch);
|
|
|
|
for (int i = 0; i < numberOfKeys; i++) {
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2022-07-25 01:53:14 +00:00
|
|
|
GateRef switchCase = env_->GetBuilder()->SwitchCase(switchBranch, keysValue[i]);
|
2021-09-04 08:06:49 +00:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
|
|
keysLabel[i].AppendPredecessor(currentLabel);
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
|
|
keysLabel[i].MergeControl(switchCase);
|
|
|
|
}
|
|
|
|
|
2022-07-25 01:53:14 +00:00
|
|
|
GateRef defaultCase = env_->GetBuilder()->DefaultCase(switchBranch);
|
2021-09-04 08:06:49 +00:00
|
|
|
defaultLabel->AppendPredecessor(currentLabel);
|
|
|
|
defaultLabel->MergeControl(defaultCase);
|
2022-07-25 01:53:14 +00:00
|
|
|
env_->SetCurrentLabel(nullptr);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::LoopBegin(Label *loopHead)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
ASSERT(loopHead);
|
2022-07-25 01:53:14 +00:00
|
|
|
auto loopControl = env_->GetBuilder()->LoopBegin(loopHead->GetControl());
|
2021-09-04 08:06:49 +00:00
|
|
|
loopHead->SetControl(loopControl);
|
|
|
|
loopHead->SetPreControl(loopControl);
|
|
|
|
loopHead->Bind();
|
2022-07-25 01:53:14 +00:00
|
|
|
env_->SetCurrentLabel(loopHead);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::LoopEnd(Label *loopHead)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
ASSERT(loopHead);
|
2022-07-25 01:53:14 +00:00
|
|
|
auto currentLabel = env_->GetCurrentLabel();
|
2021-09-04 08:06:49 +00:00
|
|
|
auto currentControl = currentLabel->GetControl();
|
2022-07-25 01:53:14 +00:00
|
|
|
auto loopend = env_->GetBuilder()->LoopEnd(currentControl);
|
2021-09-04 08:06:49 +00:00
|
|
|
currentLabel->SetControl(loopend);
|
|
|
|
loopHead->AppendPredecessor(currentLabel);
|
|
|
|
loopHead->MergeControl(loopend);
|
|
|
|
loopHead->Seal();
|
|
|
|
loopHead->MergeAllControl();
|
2021-09-26 06:47:20 +00:00
|
|
|
loopHead->MergeAllDepend();
|
2022-07-25 01:53:14 +00:00
|
|
|
env_->SetCurrentLabel(nullptr);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
// FindElementWithCache in ecmascript/layout_info-inl.h
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FindElementWithCache(GateRef glue, GateRef layoutInfo, GateRef hClass,
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef key, GateRef propsNum)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subEntry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subEntry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
|
|
|
|
DEFVARIABLE(i, VariableType::INT32(), Int32(0));
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label notExceedUpper(env);
|
|
|
|
Label exceedUpper(env);
|
|
|
|
Label afterExceedCon(env);
|
|
|
|
// 9 : Builtins Object properties number is nine
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32LessThanOrEqual(propsNum, Int32(9)), ¬ExceedUpper, &exceedUpper);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
Bind(¬ExceedUpper);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label afterLoop(env);
|
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
|
|
|
Label propsNumIsZero(env);
|
|
|
|
Label propsNumNotZero(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32Equal(propsNum, Int32(0)), &propsNumIsZero, &propsNumNotZero);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&propsNumIsZero);
|
|
|
|
Jump(&afterLoop);
|
|
|
|
Bind(&propsNumNotZero);
|
|
|
|
GateRef elementAddr = GetPropertiesAddrFromLayoutInfo(layoutInfo);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef keyInProperty = Load(VariableType::INT64(), elementAddr,
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrMul(ChangeInt32ToIntPtr(*i),
|
2022-03-31 09:26:17 +00:00
|
|
|
IntPtr(sizeof(panda::ecmascript::Properties))));
|
2021-12-17 09:18:10 +00:00
|
|
|
Label equal(env);
|
|
|
|
Label notEqual(env);
|
|
|
|
Label afterEqualCon(env);
|
2022-02-08 09:22:08 +00:00
|
|
|
Branch(Int64Equal(keyInProperty, key), &equal, ¬Equal);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&equal);
|
|
|
|
result = *i;
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(¬Equal);
|
|
|
|
Jump(&afterEqualCon);
|
|
|
|
Bind(&afterEqualCon);
|
2022-03-31 09:26:17 +00:00
|
|
|
i = Int32Add(*i, Int32(1));
|
2022-04-21 12:08:23 +00:00
|
|
|
Branch(Int32UnsignedLessThan(*i, propsNum), &loopEnd, &afterLoop);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&loopEnd);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
}
|
|
|
|
Bind(&afterLoop);
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Int32(-1);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
Bind(&exceedUpper);
|
|
|
|
Jump(&afterExceedCon);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&afterExceedCon);
|
2022-06-29 01:43:42 +00:00
|
|
|
result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(FindElementWithCache), { glue, hClass, key, propsNum });
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FindElementFromNumberDictionary(GateRef glue, GateRef elements, GateRef index)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
2021-09-09 09:40:54 +00:00
|
|
|
Label subentry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subentry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
|
2021-09-09 09:40:54 +00:00
|
|
|
Label exit(env);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef capcityoffset =
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
|
2022-03-31 09:26:17 +00:00
|
|
|
IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
|
|
|
|
GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef capacity = TaggedCastToInt32(Load(VariableType::INT64(), elements,
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrAdd(dataoffset, capcityoffset)));
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(count, VariableType::INT32(), Int32(1));
|
|
|
|
GateRef len = Int32(sizeof(int) / sizeof(uint8_t));
|
|
|
|
GateRef hash = CallRuntime(glue, RTSTUB_ID(GetHash32),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ IntToTaggedInt(index), IntToTaggedInt(len) });
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(entry, VariableType::INT32(),
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32And(TruncInt64ToInt32(ChangeTaggedPointerToInt64(hash)), Int32Sub(capacity, Int32(1))));
|
2021-09-04 08:06:49 +00:00
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label afterLoop(env);
|
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef element = GetKeyFromDictionary<NumberDictionary>(VariableType::JS_ANY(), elements, *entry);
|
2021-09-04 08:06:49 +00:00
|
|
|
Label isHole(env);
|
|
|
|
Label notHole(env);
|
|
|
|
Branch(TaggedIsHole(element), &isHole, ¬Hole);
|
|
|
|
Bind(&isHole);
|
|
|
|
Jump(&loopEnd);
|
|
|
|
Bind(¬Hole);
|
|
|
|
Label isUndefined(env);
|
|
|
|
Label notUndefined(env);
|
|
|
|
Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
|
|
|
|
Bind(&isUndefined);
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Int32(-1);
|
2021-09-09 09:40:54 +00:00
|
|
|
Jump(&exit);
|
2021-09-04 08:06:49 +00:00
|
|
|
Bind(¬Undefined);
|
|
|
|
Label isMatch(env);
|
|
|
|
Label notMatch(env);
|
2022-02-19 02:09:52 +00:00
|
|
|
Branch(Int32Equal(index, TaggedCastToInt32(element)), &isMatch, ¬Match);
|
2021-09-04 08:06:49 +00:00
|
|
|
Bind(&isMatch);
|
|
|
|
result = *entry;
|
2021-09-09 09:40:54 +00:00
|
|
|
Jump(&exit);
|
2021-09-04 08:06:49 +00:00
|
|
|
Bind(¬Match);
|
|
|
|
Jump(&loopEnd);
|
|
|
|
Bind(&loopEnd);
|
2021-10-16 10:06:22 +00:00
|
|
|
entry = GetNextPositionForHash(*entry, *count, capacity);
|
2022-03-31 09:26:17 +00:00
|
|
|
count = Int32Add(*count, Int32(1));
|
2021-09-04 08:06:49 +00:00
|
|
|
LoopEnd(&loopHead);
|
2021-09-09 09:40:54 +00:00
|
|
|
Bind(&exit);
|
2021-10-12 03:50:58 +00:00
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-10-12 03:50:58 +00:00
|
|
|
return ret;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-04-25 02:15:36 +00:00
|
|
|
// int TaggedHashTable<Derived>::FindEntry(const JSTaggedValue &key) in tagged_hash_table.h
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FindEntryFromNameDictionary(GateRef glue, GateRef elements, GateRef key)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
2021-12-17 09:18:10 +00:00
|
|
|
Label funcEntry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&funcEntry);
|
2021-09-09 09:40:54 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef capcityoffset =
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
|
2022-03-31 09:26:17 +00:00
|
|
|
IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
|
|
|
|
GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef capacity = TaggedCastToInt32(Load(VariableType::INT64(), elements,
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrAdd(dataoffset, capcityoffset)));
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(count, VariableType::INT32(), Int32(1));
|
|
|
|
DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
|
2021-12-17 09:18:10 +00:00
|
|
|
// NameDictionary::hash
|
|
|
|
Label isSymbol(env);
|
|
|
|
Label notSymbol(env);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label afterLoop(env);
|
|
|
|
Label beforeDefineHash(env);
|
|
|
|
Branch(IsSymbol(key), &isSymbol, ¬Symbol);
|
|
|
|
Bind(&isSymbol);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
hash = TaggedCastToInt32(Load(VariableType::INT64(), key,
|
2022-03-31 09:26:17 +00:00
|
|
|
IntPtr(JSSymbol::HASHFIELD_OFFSET)));
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&beforeDefineHash);
|
|
|
|
}
|
|
|
|
Bind(¬Symbol);
|
|
|
|
{
|
|
|
|
Label isString(env);
|
|
|
|
Label notString(env);
|
|
|
|
Branch(IsString(key), &isString, ¬String);
|
|
|
|
Bind(&isString);
|
|
|
|
{
|
2022-04-28 01:16:30 +00:00
|
|
|
hash = GetHashcodeFromString(glue, key);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&beforeDefineHash);
|
|
|
|
}
|
|
|
|
Bind(¬String);
|
|
|
|
{
|
|
|
|
Jump(&beforeDefineHash);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&beforeDefineHash);
|
|
|
|
// GetFirstPosition(hash, size)
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
2022-03-16 10:12:15 +00:00
|
|
|
GateRef element = GetKeyFromDictionary<NameDictionary>(VariableType::JS_ANY(), elements, *entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label isHole(env);
|
|
|
|
Label notHole(env);
|
|
|
|
Branch(TaggedIsHole(element), &isHole, ¬Hole);
|
|
|
|
{
|
|
|
|
Bind(&isHole);
|
|
|
|
{
|
|
|
|
Jump(&loopEnd);
|
|
|
|
}
|
|
|
|
Bind(¬Hole);
|
|
|
|
{
|
|
|
|
Label isUndefined(env);
|
|
|
|
Label notUndefined(env);
|
|
|
|
Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
|
|
|
|
{
|
|
|
|
Bind(&isUndefined);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Int32(-1);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Undefined);
|
|
|
|
{
|
|
|
|
Label isMatch(env);
|
|
|
|
Label notMatch(env);
|
2022-02-08 09:22:08 +00:00
|
|
|
Branch(Int64Equal(key, element), &isMatch, ¬Match);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
Bind(&isMatch);
|
|
|
|
{
|
|
|
|
result = *entry;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Match);
|
|
|
|
{
|
|
|
|
Jump(&loopEnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&loopEnd);
|
|
|
|
{
|
|
|
|
entry = GetNextPositionForHash(*entry, *count, capacity);
|
2022-03-31 09:26:17 +00:00
|
|
|
count = Int32Add(*count, Int32(1));
|
2021-12-17 09:18:10 +00:00
|
|
|
LoopEnd(&loopHead);
|
|
|
|
}
|
|
|
|
}
|
2021-09-09 09:40:54 +00:00
|
|
|
Bind(&exit);
|
2021-10-12 03:50:58 +00:00
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-10-12 03:50:58 +00:00
|
|
|
return ret;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::IsMatchInTransitionDictionary(GateRef element, GateRef key, GateRef metaData, GateRef attr)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-08-11 03:18:30 +00:00
|
|
|
return BoolAnd(Int64Equal(element, key), Int32Equal(metaData, attr));
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// metaData is int32 type
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FindEntryFromTransitionDictionary(GateRef glue, GateRef elements, GateRef key, GateRef metaData)
|
2021-09-18 09:14:04 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label funcEntry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&funcEntry);
|
2021-09-18 09:14:04 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef capcityoffset =
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrMul(IntPtr(JSTaggedValue::TaggedTypeSize()),
|
2022-03-31 09:26:17 +00:00
|
|
|
IntPtr(TaggedHashTable<NumberDictionary>::SIZE_INDEX));
|
|
|
|
GateRef dataoffset = IntPtr(TaggedArray::DATA_OFFSET);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef capacity = TaggedCastToInt32(Load(VariableType::INT64(), elements,
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrAdd(dataoffset, capcityoffset)));
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(count, VariableType::INT32(), Int32(1));
|
|
|
|
DEFVARIABLE(hash, VariableType::INT32(), Int32(0));
|
2021-12-17 09:18:10 +00:00
|
|
|
// TransitionDictionary::hash
|
2021-09-18 09:14:04 +00:00
|
|
|
Label isSymbol(env);
|
|
|
|
Label notSymbol(env);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label afterLoop(env);
|
|
|
|
Label beforeDefineHash(env);
|
|
|
|
Branch(IsSymbol(key), &isSymbol, ¬Symbol);
|
|
|
|
Bind(&isSymbol);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
hash = TaggedCastToInt32(Load(VariableType::INT64(), key,
|
2022-03-31 09:26:17 +00:00
|
|
|
IntPtr(panda::ecmascript::JSSymbol::HASHFIELD_OFFSET)));
|
2021-09-18 09:14:04 +00:00
|
|
|
Jump(&beforeDefineHash);
|
|
|
|
}
|
|
|
|
Bind(¬Symbol);
|
|
|
|
{
|
|
|
|
Label isString(env);
|
|
|
|
Label notString(env);
|
|
|
|
Branch(IsString(key), &isString, ¬String);
|
|
|
|
Bind(&isString);
|
|
|
|
{
|
2022-04-28 01:16:30 +00:00
|
|
|
hash = GetHashcodeFromString(glue, key);
|
2021-09-18 09:14:04 +00:00
|
|
|
Jump(&beforeDefineHash);
|
|
|
|
}
|
|
|
|
Bind(¬String);
|
|
|
|
{
|
|
|
|
Jump(&beforeDefineHash);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&beforeDefineHash);
|
2021-12-17 09:18:10 +00:00
|
|
|
hash = Int32Add(*hash, metaData);
|
2021-09-18 09:14:04 +00:00
|
|
|
// GetFirstPosition(hash, size)
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(entry, VariableType::INT32(), Int32And(*hash, Int32Sub(capacity, Int32(1))));
|
2021-09-18 09:14:04 +00:00
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef element = GetKeyFromDictionary<TransitionsDictionary>(VariableType::JS_ANY(), elements, *entry);
|
2021-09-18 09:14:04 +00:00
|
|
|
Label isHole(env);
|
|
|
|
Label notHole(env);
|
|
|
|
Branch(TaggedIsHole(element), &isHole, ¬Hole);
|
|
|
|
{
|
|
|
|
Bind(&isHole);
|
|
|
|
{
|
|
|
|
Jump(&loopEnd);
|
|
|
|
}
|
|
|
|
Bind(¬Hole);
|
|
|
|
{
|
|
|
|
Label isUndefined(env);
|
|
|
|
Label notUndefined(env);
|
|
|
|
Branch(TaggedIsUndefined(element), &isUndefined, ¬Undefined);
|
|
|
|
{
|
|
|
|
Bind(&isUndefined);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Int32(-1);
|
2021-09-18 09:14:04 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Undefined);
|
|
|
|
{
|
|
|
|
Label isMatch(env);
|
|
|
|
Label notMatch(env);
|
2021-12-17 09:18:10 +00:00
|
|
|
Branch(
|
|
|
|
IsMatchInTransitionDictionary(element, key, metaData,
|
|
|
|
GetAttributesFromDictionary<TransitionsDictionary>(elements, *entry)),
|
|
|
|
&isMatch, ¬Match);
|
2021-09-18 09:14:04 +00:00
|
|
|
{
|
|
|
|
Bind(&isMatch);
|
|
|
|
{
|
|
|
|
result = *entry;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Match);
|
|
|
|
{
|
|
|
|
Jump(&loopEnd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&loopEnd);
|
|
|
|
{
|
2021-10-16 10:06:22 +00:00
|
|
|
entry = GetNextPositionForHash(*entry, *count, capacity);
|
2022-03-31 09:26:17 +00:00
|
|
|
count = Int32Add(*count, Int32(1));
|
2021-09-18 09:14:04 +00:00
|
|
|
LoopEnd(&loopHead);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2021-10-12 03:50:58 +00:00
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-10-12 03:50:58 +00:00
|
|
|
return ret;
|
2021-09-18 09:14:04 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::JSObjectGetProperty(VariableType returnType, GateRef obj, GateRef hClass, GateRef attr)
|
2021-09-18 09:14:04 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-09-18 09:14:04 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, returnType, Undefined(returnType));
|
2021-09-18 09:14:04 +00:00
|
|
|
Label inlinedProp(env);
|
|
|
|
Label notInlinedProp(env);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef attrOffset = GetOffsetFieldInPropAttr(attr);
|
2021-09-18 09:14:04 +00:00
|
|
|
Branch(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp);
|
|
|
|
{
|
|
|
|
Bind(&inlinedProp);
|
|
|
|
{
|
2022-08-10 04:07:46 +00:00
|
|
|
result = GetPropertyInlinedProps(obj, hClass, attrOffset, returnType);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬InlinedProp);
|
|
|
|
{
|
|
|
|
// compute outOfLineProp offset, get it and return
|
|
|
|
GateRef array =
|
2022-03-31 09:26:17 +00:00
|
|
|
Load(VariableType::INT64(), obj, IntPtr(JSObject::PROPERTIES_OFFSET));
|
2021-12-17 09:18:10 +00:00
|
|
|
result = GetValueFromTaggedArray(returnType, array, Int32Sub(attrOffset,
|
|
|
|
GetInlinedPropertiesFromHClass(hClass)));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::JSObjectSetProperty(GateRef glue, GateRef obj, GateRef hClass, GateRef attr, GateRef value)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subEntry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subEntry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label inlinedProp(env);
|
|
|
|
Label notInlinedProp(env);
|
|
|
|
GateRef attrOffset = GetOffsetFieldInPropAttr(attr);
|
|
|
|
Branch(IsInlinedProperty(attr), &inlinedProp, ¬InlinedProp);
|
|
|
|
{
|
|
|
|
Bind(&inlinedProp);
|
|
|
|
{
|
|
|
|
SetPropertyInlinedProps(glue, obj, hClass, value, attrOffset);
|
2021-09-18 09:14:04 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬InlinedProp);
|
|
|
|
{
|
|
|
|
// compute outOfLineProp offset, get it and return
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef array = Load(VariableType::JS_POINTER(), obj,
|
2022-03-31 09:26:17 +00:00
|
|
|
IntPtr(JSObject::PROPERTIES_OFFSET));
|
2022-03-01 08:31:08 +00:00
|
|
|
SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, Int32Sub(attrOffset,
|
2021-12-31 07:51:09 +00:00
|
|
|
GetInlinedPropertiesFromHClass(hClass)), value);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::ComputePropertyCapacityInJSObj(GateRef oldLength)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subEntry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subEntry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT32(), Int32(0));
|
|
|
|
GateRef newL = Int32Add(oldLength, Int32(JSObject::PROPERTIES_GROW_SIZE));
|
2021-12-17 09:18:10 +00:00
|
|
|
Label reachMax(env);
|
|
|
|
Label notReachMax(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32GreaterThan(newL, Int32(PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES)),
|
2021-12-17 09:18:10 +00:00
|
|
|
&reachMax, ¬ReachMax);
|
|
|
|
{
|
|
|
|
Bind(&reachMax);
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Int32(PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
Bind(¬ReachMax);
|
|
|
|
result = newL;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::CallGetterHelper(GateRef glue, GateRef receiver, GateRef holder, GateRef accessor)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subEntry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subEntry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
2022-05-30 02:41:07 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
|
|
|
|
|
|
|
|
Label isInternal(env);
|
|
|
|
Label notInternal(env);
|
|
|
|
Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal);
|
|
|
|
Bind(&isInternal);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-06-01 03:38:27 +00:00
|
|
|
Label arrayLength(env);
|
|
|
|
Label tryContinue(env);
|
|
|
|
auto lengthAccessor = GetGlobalConstantValue(
|
|
|
|
VariableType::JS_POINTER(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
|
|
|
|
Branch(Int64Equal(accessor, lengthAccessor), &arrayLength, &tryContinue);
|
|
|
|
Bind(&arrayLength);
|
|
|
|
{
|
|
|
|
result = Load(VariableType::JS_ANY(), holder,
|
|
|
|
IntPtr(JSArray::LENGTH_OFFSET));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&tryContinue);
|
2022-05-30 02:41:07 +00:00
|
|
|
result = CallRuntime(glue, RTSTUB_ID(CallInternalGetter), { accessor, holder });
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
2022-05-30 02:41:07 +00:00
|
|
|
}
|
|
|
|
Bind(¬Internal);
|
|
|
|
{
|
|
|
|
auto getter = Load(VariableType::JS_ANY(), accessor,
|
|
|
|
IntPtr(AccessorData::GETTER_OFFSET));
|
|
|
|
Label objIsUndefined(env);
|
|
|
|
Label objNotUndefined(env);
|
|
|
|
Branch(TaggedIsUndefined(getter), &objIsUndefined, &objNotUndefined);
|
|
|
|
// if getter is undefined, return undefiend
|
|
|
|
Bind(&objIsUndefined);
|
|
|
|
{
|
|
|
|
result = Undefined();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotUndefined);
|
|
|
|
{
|
2022-06-17 10:26:05 +00:00
|
|
|
auto retValue = JSCallDispatch(glue, getter, Int32(0),
|
2022-05-30 02:41:07 +00:00
|
|
|
JSCallMode::CALL_GETTER, { receiver });
|
|
|
|
Label noPendingException(env);
|
|
|
|
Branch(HasPendingException(glue), &exit, &noPendingException);
|
|
|
|
Bind(&noPendingException);
|
|
|
|
{
|
|
|
|
result = retValue;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::CallSetterHelper(GateRef glue, GateRef receiver, GateRef accessor, GateRef value)
|
2022-05-30 02:41:07 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subEntry(env);
|
|
|
|
env->SubCfgEntry(&subEntry);
|
|
|
|
Label exit(env);
|
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
|
|
|
|
|
|
|
|
Label isInternal(env);
|
|
|
|
Label notInternal(env);
|
|
|
|
Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal);
|
|
|
|
Bind(&isInternal);
|
|
|
|
{
|
|
|
|
result = CallRuntime(glue, RTSTUB_ID(CallInternalSetter), { receiver, accessor, value });
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-05-30 02:41:07 +00:00
|
|
|
Bind(¬Internal);
|
|
|
|
{
|
|
|
|
auto setter = Load(VariableType::JS_ANY(), accessor,
|
|
|
|
IntPtr(AccessorData::SETTER_OFFSET));
|
|
|
|
Label objIsUndefined(env);
|
|
|
|
Label objNotUndefined(env);
|
|
|
|
Branch(TaggedIsUndefined(setter), &objIsUndefined, &objNotUndefined);
|
|
|
|
Bind(&objIsUndefined);
|
|
|
|
{
|
2022-06-16 12:58:44 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowSetterIsUndefinedException), {});
|
|
|
|
result = Exception();
|
2022-05-30 02:41:07 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotUndefined);
|
|
|
|
{
|
2022-06-17 10:26:05 +00:00
|
|
|
auto retValue = JSCallDispatch(glue, setter, Int32(1),
|
2022-05-30 02:41:07 +00:00
|
|
|
JSCallMode::CALL_SETTER, { receiver, value });
|
|
|
|
Label noPendingException(env);
|
|
|
|
Branch(HasPendingException(glue), &exit, &noPendingException);
|
|
|
|
Bind(&noPendingException);
|
|
|
|
{
|
|
|
|
result = retValue;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::ShouldCallSetter(GateRef receiver, GateRef holder, GateRef accessor, GateRef attr)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subEntry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subEntry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::BOOL(), True());
|
2021-12-17 09:18:10 +00:00
|
|
|
Label isInternal(env);
|
|
|
|
Label notInternal(env);
|
|
|
|
Branch(IsAccessorInternal(accessor), &isInternal, ¬Internal);
|
|
|
|
Bind(&isInternal);
|
|
|
|
{
|
|
|
|
Label receiverEqualsHolder(env);
|
|
|
|
Label receiverNotEqualsHolder(env);
|
2022-02-08 09:22:08 +00:00
|
|
|
Branch(Int64Equal(receiver, holder), &receiverEqualsHolder, &receiverNotEqualsHolder);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&receiverEqualsHolder);
|
|
|
|
{
|
|
|
|
result = IsWritable(attr);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&receiverNotEqualsHolder);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = False();
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬Internal);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = True();
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::JSHClassAddProperty(GateRef glue, GateRef receiver, GateRef key, GateRef attr)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subEntry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subEntry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
GateRef hclass = LoadHClass(receiver);
|
|
|
|
GateRef metaData = GetPropertyMetaDataFromAttr(attr);
|
|
|
|
GateRef newDyn = FindTransitions(glue, receiver, hclass, key, metaData);
|
|
|
|
Label findHClass(env);
|
|
|
|
Label notFindHClass(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int64Equal(newDyn, Int64(JSTaggedValue::VALUE_UNDEFINED)), ¬FindHClass, &findHClass);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&findHClass);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬FindHClass);
|
|
|
|
{
|
|
|
|
GateRef type = GetObjectType(hclass);
|
2021-12-31 07:51:09 +00:00
|
|
|
GateRef size = Int32Mul(GetInlinedPropsStartFromHClass(hclass),
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32(JSTaggedValue::TaggedTypeSize()));
|
2021-12-31 07:51:09 +00:00
|
|
|
GateRef inlineProps = GetInlinedPropertiesFromHClass(hclass);
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef newJshclass = CallRuntime(glue, RTSTUB_ID(NewEcmaDynClass),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ IntToTaggedInt(size), IntToTaggedInt(type),
|
|
|
|
IntToTaggedInt(inlineProps) });
|
2021-12-17 09:18:10 +00:00
|
|
|
CopyAllHClass(glue, newJshclass, hclass);
|
2022-03-31 09:26:17 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(UpdateLayOutAndAddTransition),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ hclass, newJshclass, key, IntToTaggedInt(attr) });
|
2021-12-17 09:18:10 +00:00
|
|
|
#if ECMASCRIPT_ENABLE_IC
|
|
|
|
NotifyHClassChanged(glue, hclass, newJshclass);
|
|
|
|
#endif
|
|
|
|
StoreHClass(glue, receiver, newJshclass);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if condition:objHandle->IsJSArray() &&
|
|
|
|
// keyHandle.GetTaggedValue() == thread->GlobalConstants()->GetConstructorString()
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::SetHasConstructorCondition(GateRef glue, GateRef receiver, GateRef key)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-21 12:08:23 +00:00
|
|
|
GateRef gConstOffset = PtrAdd(glue,
|
2022-07-25 01:53:14 +00:00
|
|
|
IntPtr(JSThread::GlueData::GetGlobalConstOffset(env_->Is32Bit())));
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef gCtorStr = Load(VariableType::JS_ANY(),
|
2021-12-17 09:18:10 +00:00
|
|
|
gConstOffset,
|
2022-03-31 09:26:17 +00:00
|
|
|
Int64Mul(Int64(sizeof(JSTaggedValue)),
|
|
|
|
Int64(static_cast<uint64_t>(ConstantIndex::CONSTRUCTOR_STRING_INDEX))));
|
2022-02-08 09:22:08 +00:00
|
|
|
GateRef isCtorStr = Int64Equal(key, gCtorStr);
|
2022-08-11 03:18:30 +00:00
|
|
|
return BoolAnd(IsJsArray(receiver), isCtorStr);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Note: set return exit node
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::AddPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef propertyAttributes)
|
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subentry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subentry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT64(), Undefined(VariableType::INT64()));
|
2021-12-17 09:18:10 +00:00
|
|
|
Label setHasCtor(env);
|
|
|
|
Label notSetHasCtor(env);
|
|
|
|
Label afterCtorCon(env);
|
|
|
|
GateRef hClass = LoadHClass(receiver);
|
|
|
|
Branch(SetHasConstructorCondition(glue, receiver, key), &setHasCtor, ¬SetHasCtor);
|
|
|
|
{
|
|
|
|
Bind(&setHasCtor);
|
2022-03-31 09:26:17 +00:00
|
|
|
SetHasConstructorToHClass(glue, hClass, Int32(1));
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&afterCtorCon);
|
|
|
|
Bind(¬SetHasCtor);
|
|
|
|
Jump(&afterCtorCon);
|
|
|
|
}
|
|
|
|
Bind(&afterCtorCon);
|
|
|
|
// 0x111 : default attribute for property: writable, enumerable, configurable
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(attr, VariableType::INT32(), propertyAttributes);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef numberOfProps = GetNumberOfPropsFromHClass(hClass);
|
|
|
|
GateRef inlinedProperties = GetInlinedPropertiesFromHClass(hClass);
|
|
|
|
Label hasUnusedInProps(env);
|
|
|
|
Label noUnusedInProps(env);
|
|
|
|
Label afterInPropsCon(env);
|
2022-04-21 12:08:23 +00:00
|
|
|
Branch(Int32UnsignedLessThan(numberOfProps, inlinedProperties), &hasUnusedInProps, &noUnusedInProps);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
Bind(&noUnusedInProps);
|
|
|
|
Jump(&afterInPropsCon);
|
|
|
|
Bind(&hasUnusedInProps);
|
|
|
|
{
|
|
|
|
SetPropertyInlinedProps(glue, receiver, hClass, value, numberOfProps);
|
|
|
|
attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
|
2022-03-31 09:26:17 +00:00
|
|
|
attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(1)); // 1: set inInlineProps true
|
2021-12-17 09:18:10 +00:00
|
|
|
JSHClassAddProperty(glue, receiver, key, *attr);
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Undefined(VariableType::INT64());
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&afterInPropsCon);
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(array, VariableType::JS_POINTER(), GetPropertiesArray(receiver));
|
|
|
|
DEFVARIABLE(length, VariableType::INT32(), GetLengthOfTaggedArray(*array));
|
2021-12-17 09:18:10 +00:00
|
|
|
Label lenIsZero(env);
|
|
|
|
Label lenNotZero(env);
|
|
|
|
Label afterLenCon(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32Equal(*length, Int32(0)), &lenIsZero, &lenNotZero);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
Bind(&lenIsZero);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
length = Int32(JSObject::MIN_PROPERTIES_LENGTH);
|
2022-08-29 07:10:59 +00:00
|
|
|
array = CallRuntime(glue, RTSTUB_ID(NewTaggedArray), { IntToTaggedInt(*length) });
|
2022-06-10 07:35:16 +00:00
|
|
|
SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&afterLenCon);
|
|
|
|
}
|
|
|
|
Bind(&lenNotZero);
|
|
|
|
Jump(&afterLenCon);
|
|
|
|
}
|
|
|
|
Bind(&afterLenCon);
|
|
|
|
Label isDictMode(env);
|
|
|
|
Label notDictMode(env);
|
|
|
|
Branch(IsDictionaryMode(*array), &isDictMode, ¬DictMode);
|
|
|
|
{
|
|
|
|
Bind(&isDictMode);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
|
2022-08-29 07:10:59 +00:00
|
|
|
{receiver, *array, key, value, IntToTaggedInt(*attr), TaggedFalse()});
|
2022-06-10 07:35:16 +00:00
|
|
|
SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
|
2021-09-18 09:14:04 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(¬DictMode);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
attr = SetIsInlinePropsFieldInPropAttr(*attr, Int32(0));
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef outProps = Int32Sub(numberOfProps, inlinedProperties);
|
|
|
|
Label isArrayFull(env);
|
|
|
|
Label arrayNotFull(env);
|
|
|
|
Label afterArrLenCon(env);
|
2022-02-08 09:22:08 +00:00
|
|
|
Branch(Int32Equal(*length, outProps), &isArrayFull, &arrayNotFull);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
Bind(&isArrayFull);
|
|
|
|
{
|
|
|
|
Label ChangeToDict(env);
|
|
|
|
Label notChangeToDict(env);
|
|
|
|
Label afterDictChangeCon(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32Equal(*length, Int32(JSHClass::MAX_CAPACITY_OF_OUT_OBJECTS)),
|
2021-12-17 09:18:10 +00:00
|
|
|
&ChangeToDict, ¬ChangeToDict);
|
|
|
|
{
|
|
|
|
Bind(&ChangeToDict);
|
|
|
|
{
|
|
|
|
attr = SetDictionaryOrderFieldInPropAttr(*attr,
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32(PropertyAttributes::MAX_CAPACITY_OF_PROPERTIES));
|
|
|
|
GateRef res = CallRuntime(glue, RTSTUB_ID(NameDictPutIfAbsent),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ receiver, *array, key, value, IntToTaggedInt(*attr), TaggedTrue() });
|
2022-06-10 07:35:16 +00:00
|
|
|
SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, res);
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Undefined(VariableType::INT64());
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬ChangeToDict);
|
|
|
|
Jump(&afterDictChangeCon);
|
|
|
|
}
|
|
|
|
Bind(&afterDictChangeCon);
|
|
|
|
GateRef capacity = ComputePropertyCapacityInJSObj(*length);
|
2022-03-31 09:26:17 +00:00
|
|
|
array = CallRuntime(glue, RTSTUB_ID(CopyArray),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ *array, IntToTaggedInt(*length), IntToTaggedInt(capacity) });
|
2022-06-10 07:35:16 +00:00
|
|
|
SetPropertiesArray(VariableType::JS_POINTER(), glue, receiver, *array);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&afterArrLenCon);
|
|
|
|
}
|
|
|
|
Bind(&arrayNotFull);
|
|
|
|
Jump(&afterArrLenCon);
|
|
|
|
}
|
|
|
|
Bind(&afterArrLenCon);
|
|
|
|
{
|
|
|
|
attr = SetOffsetFieldInPropAttr(*attr, numberOfProps);
|
|
|
|
JSHClassAddProperty(glue, receiver, key, *attr);
|
2022-03-01 08:31:08 +00:00
|
|
|
SetValueToTaggedArray(VariableType::JS_ANY(), glue, *array, outProps, value);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
2021-09-18 09:14:04 +00:00
|
|
|
}
|
|
|
|
Bind(&exit);
|
2021-10-12 03:50:58 +00:00
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-10-12 03:50:58 +00:00
|
|
|
return ret;
|
2021-09-18 09:14:04 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::ThrowTypeAndReturn(GateRef glue, int messageId, GateRef val)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef msgIntId = Int32(messageId);
|
2022-08-29 07:10:59 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(msgIntId) });
|
2021-09-04 08:06:49 +00:00
|
|
|
Return(val);
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::TaggedToRepresentation(GateRef value)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
2021-09-09 09:40:54 +00:00
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-09-09 09:40:54 +00:00
|
|
|
Label exit(env);
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(resultRep, VariableType::INT64(),
|
2022-03-31 09:26:17 +00:00
|
|
|
Int64(static_cast<int32_t>(Representation::OBJECT)));
|
2021-09-04 08:06:49 +00:00
|
|
|
Label isInt(env);
|
|
|
|
Label notInt(env);
|
|
|
|
|
|
|
|
Branch(TaggedIsInt(value), &isInt, ¬Int);
|
|
|
|
Bind(&isInt);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
resultRep = Int64(static_cast<int32_t>(Representation::INT));
|
2021-09-09 09:40:54 +00:00
|
|
|
Jump(&exit);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
Bind(¬Int);
|
|
|
|
{
|
|
|
|
Label isDouble(env);
|
|
|
|
Label notDouble(env);
|
|
|
|
Branch(TaggedIsDouble(value), &isDouble, ¬Double);
|
|
|
|
Bind(&isDouble);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
resultRep = Int64(static_cast<int32_t>(Representation::DOUBLE));
|
2021-09-09 09:40:54 +00:00
|
|
|
Jump(&exit);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
Bind(¬Double);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
resultRep = Int64(static_cast<int32_t>(Representation::OBJECT));
|
2021-09-09 09:40:54 +00:00
|
|
|
Jump(&exit);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-09 09:40:54 +00:00
|
|
|
Bind(&exit);
|
2021-10-12 03:50:58 +00:00
|
|
|
auto ret = *resultRep;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-10-12 03:50:58 +00:00
|
|
|
return ret;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-07-25 01:53:14 +00:00
|
|
|
auto depend = env_->GetCurrentLabel()->GetDepend();
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef result;
|
2022-07-25 01:53:14 +00:00
|
|
|
if (env_->IsArch64Bit()) {
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef ptr = Int64Add(base, offset);
|
2022-04-16 08:54:51 +00:00
|
|
|
if (type == VariableType::NATIVE_POINTER()) {
|
2022-03-01 08:31:08 +00:00
|
|
|
type = VariableType::INT64();
|
2021-12-23 06:55:22 +00:00
|
|
|
}
|
2022-07-25 01:53:14 +00:00
|
|
|
result = env_->GetCircuit()->NewGate(OpCode(OpCode::STORE), 0, { depend, value, ptr }, type.GetGateType());
|
|
|
|
env_->GetCurrentLabel()->SetDepend(result);
|
|
|
|
} else if (env_->IsArch32Bit()) {
|
2022-04-16 08:54:51 +00:00
|
|
|
if (type == VariableType::NATIVE_POINTER()) {
|
2022-03-01 08:31:08 +00:00
|
|
|
type = VariableType::INT32();
|
2021-12-23 06:55:22 +00:00
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef ptr = Int32Add(base, offset);
|
2022-07-25 01:53:14 +00:00
|
|
|
result = env_->GetCircuit()->NewGate(OpCode(OpCode::STORE), 0, { depend, value, ptr }, type.GetGateType());
|
|
|
|
env_->GetCurrentLabel()->SetDepend(result);
|
2021-10-28 07:06:25 +00:00
|
|
|
} else {
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2022-03-01 08:31:08 +00:00
|
|
|
if (type == VariableType::JS_POINTER() || type == VariableType::JS_ANY()) {
|
2021-12-17 09:18:10 +00:00
|
|
|
SetValueWithBarrier(glue, base, offset, value);
|
2021-10-28 07:06:25 +00:00
|
|
|
}
|
2022-03-21 03:38:21 +00:00
|
|
|
return;
|
2021-10-28 07:06:25 +00:00
|
|
|
}
|
2021-10-30 08:43:57 +00:00
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label isHeapObject(env);
|
2022-02-07 09:23:03 +00:00
|
|
|
Label isVailedIndex(env);
|
|
|
|
Label notValidIndex(env);
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
Branch(TaggedIsHeapObject(value), &isHeapObject, &exit);
|
|
|
|
Bind(&isHeapObject);
|
|
|
|
{
|
2022-02-07 09:23:03 +00:00
|
|
|
GateRef objectRegion = ObjectAddressToRange(obj);
|
|
|
|
GateRef valueRegion = ObjectAddressToRange(value);
|
2022-04-21 12:08:23 +00:00
|
|
|
GateRef slotAddr = PtrAdd(TaggedCastToIntPtr(obj), offset);
|
2022-03-25 01:31:39 +00:00
|
|
|
GateRef objectNotInYoung = BoolNot(InYoungGeneration(objectRegion));
|
|
|
|
GateRef valueRegionInYoung = InYoungGeneration(valueRegion);
|
2022-02-07 09:23:03 +00:00
|
|
|
Branch(BoolAnd(objectNotInYoung, valueRegionInYoung), &isVailedIndex, ¬ValidIndex);
|
|
|
|
Bind(&isVailedIndex);
|
|
|
|
{
|
2022-07-25 01:53:14 +00:00
|
|
|
GateRef loadOffset = IntPtr(Region::PackedData::GetOldToNewSetOffset(env_->Is32Bit()));
|
2022-04-16 08:54:51 +00:00
|
|
|
auto oldToNewSet = Load(VariableType::NATIVE_POINTER(), objectRegion, loadOffset);
|
2022-02-07 09:23:03 +00:00
|
|
|
Label isNullPtr(env);
|
|
|
|
Label notNullPtr(env);
|
2022-05-19 04:48:40 +00:00
|
|
|
Branch(IntPtrEuqal(oldToNewSet, IntPtr(0)), &isNullPtr, ¬NullPtr);
|
2022-02-07 09:23:03 +00:00
|
|
|
Bind(¬NullPtr);
|
|
|
|
{
|
2022-04-22 03:03:38 +00:00
|
|
|
// (slotAddr - this) >> TAGGED_TYPE_SIZE_LOG
|
|
|
|
GateRef bitOffsetPtr = IntPtrLSR(PtrSub(slotAddr, objectRegion), IntPtr(TAGGED_TYPE_SIZE_LOG));
|
2022-04-16 10:04:54 +00:00
|
|
|
GateRef bitOffset = TruncPtrToInt32(bitOffsetPtr);
|
|
|
|
GateRef bitPerWordLog2 = Int32(GCBitset::BIT_PER_WORD_LOG2);
|
|
|
|
GateRef bytePerWord = Int32(GCBitset::BYTE_PER_WORD);
|
|
|
|
// bitOffset >> BIT_PER_WORD_LOG2
|
|
|
|
GateRef index = Int32LSR(bitOffset, bitPerWordLog2);
|
|
|
|
GateRef byteIndex = Int32Mul(index, bytePerWord);
|
|
|
|
// bitset_[index] |= mask;
|
|
|
|
GateRef bitsetData = PtrAdd(oldToNewSet, IntPtr(RememberedSet::GCBITSET_DATA_OFFSET));
|
|
|
|
GateRef oldsetValue = Load(VariableType::INT32(), bitsetData, byteIndex);
|
|
|
|
GateRef newmapValue = Int32Or(oldsetValue, GetBitMask(bitOffset));
|
|
|
|
|
|
|
|
Store(VariableType::INT32(), glue, bitsetData, byteIndex, newmapValue);
|
2022-02-07 09:23:03 +00:00
|
|
|
Jump(¬ValidIndex);
|
|
|
|
}
|
|
|
|
Bind(&isNullPtr);
|
|
|
|
{
|
2022-06-29 01:43:42 +00:00
|
|
|
UpdateLeaveFrameAndCallNGCRuntime(glue,
|
2022-04-16 10:04:54 +00:00
|
|
|
RTSTUB_ID(InsertOldToNewRSet),
|
2022-02-23 08:50:04 +00:00
|
|
|
{ glue, objectRegion, slotAddr });
|
2022-02-07 09:23:03 +00:00
|
|
|
Jump(¬ValidIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬ValidIndex);
|
|
|
|
{
|
2022-03-12 09:29:12 +00:00
|
|
|
Label marking(env);
|
|
|
|
bool isArch32 = GetEnvironment()->Is32Bit();
|
|
|
|
GateRef stateBitFieldAddr = Int64Add(glue,
|
2022-03-31 09:26:17 +00:00
|
|
|
Int64(JSThread::GlueData::GetStateBitFieldOffset(isArch32)));
|
|
|
|
GateRef stateBitField = Load(VariableType::INT64(), stateBitFieldAddr, Int64(0));
|
|
|
|
Branch(Int64Equal(stateBitField, Int64(0)), &exit, &marking);
|
2022-03-12 09:29:12 +00:00
|
|
|
|
|
|
|
Bind(&marking);
|
2022-06-29 01:43:42 +00:00
|
|
|
UpdateLeaveFrameAndCallNGCRuntime(glue,
|
2022-03-30 07:12:36 +00:00
|
|
|
RTSTUB_ID(MarkingBarrier), {
|
2022-03-02 02:21:05 +00:00
|
|
|
glue, slotAddr, objectRegion, TaggedCastToIntPtr(value), valueRegion });
|
2022-02-07 09:23:03 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2021-10-28 07:06:25 +00:00
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&exit);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2021-10-16 10:06:22 +00:00
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::TaggedIsBigInt(GateRef obj)
|
2022-04-28 01:16:30 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
|
|
|
env->SubCfgEntry(&entry);
|
|
|
|
Label exit(env);
|
|
|
|
DEFVARIABLE(result, VariableType::BOOL(), False());
|
|
|
|
Label isHeapObject(env);
|
|
|
|
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
|
|
|
|
Bind(&isHeapObject);
|
|
|
|
{
|
|
|
|
result = Int32Equal(GetObjectType(LoadHClass(obj)),
|
|
|
|
Int32(static_cast<int32_t>(JSType::BIGINT)));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::IsUtf16String(GateRef string)
|
2021-10-16 10:06:22 +00:00
|
|
|
{
|
|
|
|
// compressedStringsEnabled fixed to true constant
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
|
2022-02-08 09:22:08 +00:00
|
|
|
return Int32Equal(
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
|
|
|
|
Int32(EcmaString::STRING_UNCOMPRESSED));
|
2021-10-16 10:06:22 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::IsUtf8String(GateRef string)
|
2021-10-16 10:06:22 +00:00
|
|
|
{
|
|
|
|
// compressedStringsEnabled fixed to true constant
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
|
2022-02-08 09:22:08 +00:00
|
|
|
return Int32Equal(
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32And(len, Int32(EcmaString::STRING_COMPRESSED_BIT)),
|
|
|
|
Int32(EcmaString::STRING_COMPRESSED));
|
2021-10-16 10:06:22 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::IsInternalString(GateRef string)
|
2021-10-16 10:06:22 +00:00
|
|
|
{
|
|
|
|
// compressedStringsEnabled fixed to true constant
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef len = Load(VariableType::INT32(), string, IntPtr(EcmaString::MIX_LENGTH_OFFSET));
|
2022-02-08 09:22:08 +00:00
|
|
|
return Int32NotEqual(
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32And(len, Int32(EcmaString::STRING_INTERN_BIT)),
|
|
|
|
Int32(0));
|
2021-10-16 10:06:22 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::IsDigit(GateRef ch)
|
2021-10-16 10:06:22 +00:00
|
|
|
{
|
2022-08-11 03:18:30 +00:00
|
|
|
return BoolAnd(Int32LessThanOrEqual(ch, Int32('9')),
|
|
|
|
Int32GreaterThanOrEqual(ch, Int32('0')));
|
2021-10-16 10:06:22 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::StringToElementIndex(GateRef string)
|
2021-10-16 10:06:22 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-10-16 10:06:22 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
|
2021-10-16 10:06:22 +00:00
|
|
|
Label greatThanZero(env);
|
|
|
|
Label inRange(env);
|
2022-04-06 09:02:18 +00:00
|
|
|
auto len = GetLengthFromString(string);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
|
2021-10-16 10:06:22 +00:00
|
|
|
Bind(&greatThanZero);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32GreaterThan(len, Int32(MAX_INDEX_LEN)), &exit, &inRange);
|
2021-10-16 10:06:22 +00:00
|
|
|
Bind(&inRange);
|
|
|
|
{
|
2022-04-21 12:08:23 +00:00
|
|
|
GateRef dataUtf16 = PtrAdd(string, IntPtr(EcmaString::DATA_OFFSET));
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(c, VariableType::INT32(), Int32(0));
|
2021-10-16 10:06:22 +00:00
|
|
|
Label isUtf16(env);
|
|
|
|
Label isUtf8(env);
|
|
|
|
Label getChar1(env);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef isUtf16String = IsUtf16String(string);
|
2021-10-16 10:06:22 +00:00
|
|
|
Branch(isUtf16String, &isUtf16, &isUtf8);
|
|
|
|
Bind(&isUtf16);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
c = ZExtInt16ToInt32(Load(VariableType::INT16(), dataUtf16));
|
2021-10-16 10:06:22 +00:00
|
|
|
Jump(&getChar1);
|
|
|
|
}
|
|
|
|
Bind(&isUtf8);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16));
|
2021-10-16 10:06:22 +00:00
|
|
|
Jump(&getChar1);
|
|
|
|
}
|
|
|
|
Bind(&getChar1);
|
|
|
|
{
|
|
|
|
Label isDigitZero(env);
|
|
|
|
Label notDigitZero(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32Equal(*c, Int32('0')), &isDigitZero, ¬DigitZero);
|
2021-10-16 10:06:22 +00:00
|
|
|
Bind(&isDigitZero);
|
|
|
|
{
|
|
|
|
Label lengthIsOne(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
|
2021-10-16 10:06:22 +00:00
|
|
|
Bind(&lengthIsOne);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Int32(0);
|
2021-10-16 10:06:22 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬DigitZero);
|
|
|
|
{
|
|
|
|
Label isDigit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(i, VariableType::INT32(), Int32(1));
|
|
|
|
DEFVARIABLE(n, VariableType::INT32(), Int32Sub(*c, Int32('0')));
|
2021-10-16 10:06:22 +00:00
|
|
|
Branch(IsDigit(*c), &isDigit, &exit);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label afterLoop(env);
|
|
|
|
Bind(&isDigit);
|
2022-04-21 12:08:23 +00:00
|
|
|
Branch(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
|
2021-10-16 10:06:22 +00:00
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
2022-03-22 03:07:15 +00:00
|
|
|
Label isUtf16A(env);
|
2021-10-16 10:06:22 +00:00
|
|
|
Label notUtf16(env);
|
|
|
|
Label getChar2(env);
|
2022-03-22 03:07:15 +00:00
|
|
|
Branch(isUtf16String, &isUtf16A, ¬Utf16);
|
|
|
|
Bind(&isUtf16A);
|
2021-10-16 10:06:22 +00:00
|
|
|
{
|
2021-10-28 13:32:52 +00:00
|
|
|
// 2 : 2 means utf16 char width is two bytes
|
2022-04-21 12:08:23 +00:00
|
|
|
auto charOffset = PtrMul(ChangeInt32ToIntPtr(*i), IntPtr(2));
|
2022-03-01 08:31:08 +00:00
|
|
|
c = ZExtInt16ToInt32(Load(VariableType::INT16(), dataUtf16, charOffset));
|
2021-10-16 10:06:22 +00:00
|
|
|
Jump(&getChar2);
|
|
|
|
}
|
|
|
|
Bind(¬Utf16);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
c = ZExtInt8ToInt32(Load(VariableType::INT8(), dataUtf16, ChangeInt32ToIntPtr(*i)));
|
2021-10-16 10:06:22 +00:00
|
|
|
Jump(&getChar2);
|
|
|
|
}
|
|
|
|
Bind(&getChar2);
|
|
|
|
{
|
|
|
|
Label isDigit2(env);
|
|
|
|
Label notDigit2(env);
|
|
|
|
Branch(IsDigit(*c), &isDigit2, ¬Digit2);
|
|
|
|
Bind(&isDigit2);
|
|
|
|
{
|
2021-10-26 12:05:25 +00:00
|
|
|
// 10 means the base of digit is 10.
|
2022-03-31 09:26:17 +00:00
|
|
|
n = Int32Add(Int32Mul(*n, Int32(10)),
|
|
|
|
Int32Sub(*c, Int32('0')));
|
|
|
|
i = Int32Add(*i, Int32(1));
|
2022-04-21 12:08:23 +00:00
|
|
|
Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
|
2021-10-16 10:06:22 +00:00
|
|
|
}
|
|
|
|
Bind(¬Digit2);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&loopEnd);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
Bind(&afterLoop);
|
|
|
|
{
|
|
|
|
Label lessThanMaxIndex(env);
|
2022-04-21 12:08:23 +00:00
|
|
|
Branch(Int32UnsignedLessThan(*n, Int32(JSObject::MAX_ELEMENT_INDEX)),
|
2021-10-16 10:06:22 +00:00
|
|
|
&lessThanMaxIndex, &exit);
|
|
|
|
Bind(&lessThanMaxIndex);
|
|
|
|
{
|
|
|
|
result = *n;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2021-10-22 01:15:12 +00:00
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-10-22 01:15:12 +00:00
|
|
|
return ret;
|
2021-10-16 10:06:22 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::TryToElementsIndex(GateRef key)
|
2021-10-16 10:06:22 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-10-16 10:06:22 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label isKeyInt(env);
|
|
|
|
Label notKeyInt(env);
|
|
|
|
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(resultKey, VariableType::INT32(), Int32(-1));
|
2021-10-16 10:06:22 +00:00
|
|
|
Branch(TaggedIsInt(key), &isKeyInt, ¬KeyInt);
|
|
|
|
Bind(&isKeyInt);
|
|
|
|
{
|
|
|
|
resultKey = TaggedCastToInt32(key);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬KeyInt);
|
|
|
|
{
|
|
|
|
Label isString(env);
|
|
|
|
Label notString(env);
|
|
|
|
Branch(TaggedIsString(key), &isString, ¬String);
|
|
|
|
Bind(&isString);
|
|
|
|
{
|
|
|
|
resultKey = StringToElementIndex(key);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬String);
|
|
|
|
{
|
|
|
|
Label isDouble(env);
|
|
|
|
Branch(TaggedIsDouble(key), &isDouble, &exit);
|
|
|
|
Bind(&isDouble);
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef number = TaggedCastToDouble(key);
|
|
|
|
GateRef integer = ChangeFloat64ToInt32(number);
|
2021-10-16 10:06:22 +00:00
|
|
|
Label isEqual(env);
|
2021-10-25 12:50:39 +00:00
|
|
|
Branch(DoubleEqual(number, ChangeInt32ToFloat64(integer)), &isEqual, &exit);
|
2021-10-16 10:06:22 +00:00
|
|
|
Bind(&isEqual);
|
|
|
|
{
|
|
|
|
resultKey = integer;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2021-10-22 01:15:12 +00:00
|
|
|
auto ret = *resultKey;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-10-22 01:15:12 +00:00
|
|
|
return ret;
|
2021-10-16 10:06:22 +00:00
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::LoadFromField(GateRef receiver, GateRef handlerInfo)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label handlerInfoIsInlinedProps(env);
|
|
|
|
Label handlerInfoNotInlinedProps(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef index = HandlerBaseGetOffset(handlerInfo);
|
|
|
|
Branch(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
|
|
|
|
Bind(&handlerInfoIsInlinedProps);
|
|
|
|
{
|
2022-04-21 12:08:23 +00:00
|
|
|
result = Load(VariableType::JS_ANY(), receiver, PtrMul(ChangeInt32ToIntPtr(index),
|
2022-03-31 09:26:17 +00:00
|
|
|
IntPtr(JSTaggedValue::TaggedTypeSize())));
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&handlerInfoNotInlinedProps);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
result = GetValueFromTaggedArray(VariableType::JS_ANY(), GetPropertiesArray(receiver), index);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::LoadGlobal(GateRef cell)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label cellIsInvalid(env);
|
|
|
|
Label cellNotInvalid(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2021-12-17 09:18:10 +00:00
|
|
|
Branch(IsInvalidPropertyBox(cell), &cellIsInvalid, &cellNotInvalid);
|
|
|
|
Bind(&cellIsInvalid);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&cellNotInvalid);
|
|
|
|
{
|
|
|
|
result = GetValueFromPropertyBox(cell);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::CheckPolyHClass(GateRef cachedValue, GateRef hclass)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label iLessLength(env);
|
|
|
|
Label hasHclass(env);
|
|
|
|
Label cachedValueNotWeak(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(i, VariableType::INT32(), Int32(0));
|
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2021-12-17 09:18:10 +00:00
|
|
|
Branch(TaggedIsWeak(cachedValue), &exit, &cachedValueNotWeak);
|
|
|
|
Bind(&cachedValueNotWeak);
|
|
|
|
{
|
2022-02-19 02:09:52 +00:00
|
|
|
GateRef length = GetLengthOfTaggedArray(cachedValue);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
2022-04-21 12:08:23 +00:00
|
|
|
Branch(Int32UnsignedLessThan(*i, length), &iLessLength, &exit);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&iLessLength);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef element = GetValueFromTaggedArray(VariableType::JS_ANY(), cachedValue, *i);
|
2022-02-19 02:09:52 +00:00
|
|
|
Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(element), hclass), &hasHclass, &loopEnd);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&hasHclass);
|
2022-03-01 08:31:08 +00:00
|
|
|
result = GetValueFromTaggedArray(VariableType::JS_ANY(), cachedValue,
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(*i, Int32(1)));
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&loopEnd);
|
2022-03-31 09:26:17 +00:00
|
|
|
i = Int32Add(*i, Int32(2)); // 2 means one ic, two slot
|
2021-12-17 09:18:10 +00:00
|
|
|
LoopEnd(&loopHead);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::LoadICWithHandler(GateRef glue, GateRef receiver, GateRef argHolder, GateRef argHandler)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label handlerIsInt(env);
|
|
|
|
Label handlerNotInt(env);
|
|
|
|
Label handlerInfoIsField(env);
|
|
|
|
Label handlerInfoNotField(env);
|
|
|
|
Label handlerInfoIsNonExist(env);
|
|
|
|
Label handlerInfoNotNonExist(env);
|
2022-02-19 02:09:52 +00:00
|
|
|
Label handlerIsPrototypeHandler(env);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label handlerNotPrototypeHandler(env);
|
|
|
|
Label cellHasChanged(env);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
|
|
|
|
DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
|
2021-12-17 09:18:10 +00:00
|
|
|
|
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
|
|
|
|
Bind(&handlerIsInt);
|
|
|
|
{
|
|
|
|
GateRef handlerInfo = TaggedCastToInt32(*handler);
|
|
|
|
Branch(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
|
|
|
|
Bind(&handlerInfoIsField);
|
|
|
|
{
|
|
|
|
result = LoadFromField(*holder, handlerInfo);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&handlerInfoNotField);
|
|
|
|
{
|
|
|
|
Branch(IsNonExist(handlerInfo), &handlerInfoIsNonExist, &handlerInfoNotNonExist);
|
|
|
|
Bind(&handlerInfoIsNonExist);
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(&handlerInfoNotNonExist);
|
|
|
|
GateRef accessor = LoadFromField(*holder, handlerInfo);
|
2022-05-30 02:41:07 +00:00
|
|
|
result = CallGetterHelper(glue, receiver, *holder, accessor);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&handlerNotInt);
|
2022-02-19 02:09:52 +00:00
|
|
|
Branch(TaggedIsPrototypeHandler(*handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
|
|
|
|
Bind(&handlerIsPrototypeHandler);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
GateRef cellValue = GetProtoCell(*handler);
|
2022-02-19 02:09:52 +00:00
|
|
|
Branch(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&cellHasChanged);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Hole();
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&loopEnd);
|
2021-12-17 09:18:10 +00:00
|
|
|
holder = GetPrototypeHandlerHolder(*handler);
|
|
|
|
handler = GetPrototypeHandlerHandlerInfo(*handler);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&handlerNotPrototypeHandler);
|
|
|
|
result = LoadGlobal(*handler);
|
|
|
|
Jump(&exit);
|
|
|
|
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::LoadElement(GateRef receiver, GateRef key)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label indexLessZero(env);
|
|
|
|
Label indexNotLessZero(env);
|
|
|
|
Label lengthLessIndex(env);
|
|
|
|
Label lengthNotLessIndex(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef index = TryToElementsIndex(key);
|
2022-06-30 12:23:06 +00:00
|
|
|
Branch(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&indexLessZero);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&indexNotLessZero);
|
|
|
|
{
|
2022-02-19 02:09:52 +00:00
|
|
|
GateRef elements = GetElementsArray(receiver);
|
|
|
|
Branch(Int32LessThanOrEqual(GetLengthOfTaggedArray(elements), index), &lengthLessIndex, &lengthNotLessIndex);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&lengthLessIndex);
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(&lengthNotLessIndex);
|
2022-03-01 08:31:08 +00:00
|
|
|
result = GetValueFromTaggedArray(VariableType::JS_ANY(), elements, index);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::ICStoreElement(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef handler)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label indexLessZero(env);
|
|
|
|
Label indexNotLessZero(env);
|
|
|
|
Label handerInfoIsJSArray(env);
|
|
|
|
Label handerInfoNotJSArray(env);
|
|
|
|
Label indexGreaterLength(env);
|
|
|
|
Label indexGreaterCapacity(env);
|
2022-02-19 02:09:52 +00:00
|
|
|
Label callRuntime(env);
|
|
|
|
Label storeElement(env);
|
|
|
|
Label handlerIsInt(env);
|
|
|
|
Label handlerNotInt(env);
|
|
|
|
Label cellHasChanged(env);
|
|
|
|
Label cellHasNotChanged(env);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT64(), Hole(VariableType::INT64()));
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(varHandler, VariableType::JS_ANY(), handler);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef index = TryToElementsIndex(key);
|
2022-06-30 12:23:06 +00:00
|
|
|
Branch(Int32LessThan(index, Int32(0)), &indexLessZero, &indexNotLessZero);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&indexLessZero);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&indexNotLessZero);
|
|
|
|
{
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
Branch(TaggedIsInt(*varHandler), &handlerIsInt, &handlerNotInt);
|
|
|
|
Bind(&handlerIsInt);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-03-26 09:45:25 +00:00
|
|
|
GateRef handlerInfo = TaggedCastToInt32(*varHandler);
|
2022-02-19 02:09:52 +00:00
|
|
|
Branch(HandlerBaseIsJSArray(handlerInfo), &handerInfoIsJSArray, &handerInfoNotJSArray);
|
|
|
|
Bind(&handerInfoIsJSArray);
|
|
|
|
{
|
|
|
|
GateRef oldLength = GetArrayLength(receiver);
|
|
|
|
Branch(Int32GreaterThanOrEqual(index, oldLength), &indexGreaterLength, &handerInfoNotJSArray);
|
|
|
|
Bind(&indexGreaterLength);
|
2022-03-01 08:31:08 +00:00
|
|
|
Store(VariableType::INT64(), glue, receiver,
|
2022-08-29 07:10:59 +00:00
|
|
|
IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET),
|
|
|
|
IntToTaggedInt(Int32Add(index, Int32(1))));
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&handerInfoNotJSArray);
|
|
|
|
}
|
|
|
|
Bind(&handerInfoNotJSArray);
|
|
|
|
{
|
|
|
|
GateRef elements = GetElementsArray(receiver);
|
|
|
|
GateRef capacity = GetLengthOfTaggedArray(elements);
|
|
|
|
Branch(Int32GreaterThanOrEqual(index, capacity), &callRuntime, &storeElement);
|
|
|
|
Bind(&callRuntime);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = ChangeTaggedPointerToInt64(CallRuntime(glue,
|
|
|
|
RTSTUB_ID(TaggedArraySetValue),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ receiver, value, elements, IntToTaggedInt(index),
|
|
|
|
IntToTaggedInt(capacity) }));
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&storeElement);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, value);
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Undefined(VariableType::INT64());
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&handlerNotInt);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-02-19 02:09:52 +00:00
|
|
|
GateRef cellValue = GetProtoCell(*varHandler);
|
|
|
|
Branch(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
|
|
|
|
Bind(&cellHasChanged);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&loopEnd);
|
|
|
|
{
|
|
|
|
varHandler = GetPrototypeHandlerHandlerInfo(*varHandler);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetArrayLength(GateRef object)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label lengthIsInt(env);
|
|
|
|
Label lengthNotInt(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT32(), Int32(0));
|
|
|
|
GateRef lengthOffset = IntPtr(panda::ecmascript::JSArray::LENGTH_OFFSET);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef length = Load(VariableType::INT64(), object, lengthOffset);
|
2021-12-17 09:18:10 +00:00
|
|
|
Branch(TaggedIsInt(length), &lengthIsInt, &lengthNotInt);
|
|
|
|
Bind(&lengthIsInt);
|
|
|
|
{
|
|
|
|
result = TaggedCastToInt32(length);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&lengthNotInt);
|
|
|
|
{
|
|
|
|
result = ChangeFloat64ToInt32(TaggedCastToDouble(length));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-29 07:27:17 +00:00
|
|
|
GateRef StubBuilder::StoreICWithHandler(GateRef glue, GateRef receiver, GateRef argHolder,
|
|
|
|
GateRef value, GateRef argHandler)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label handlerIsInt(env);
|
|
|
|
Label handlerNotInt(env);
|
|
|
|
Label handlerInfoIsField(env);
|
|
|
|
Label handlerInfoNotField(env);
|
|
|
|
Label handlerIsTransitionHandler(env);
|
|
|
|
Label handlerNotTransitionHandler(env);
|
|
|
|
Label handlerIsPrototypeHandler(env);
|
|
|
|
Label handlerNotPrototypeHandler(env);
|
|
|
|
Label handlerIsPropertyBox(env);
|
|
|
|
Label handlerNotPropertyBox(env);
|
|
|
|
Label cellHasChanged(env);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT64(), Undefined(VariableType::INT64()));
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(holder, VariableType::JS_ANY(), argHolder);
|
|
|
|
DEFVARIABLE(handler, VariableType::JS_ANY(), argHandler);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsInt(*handler), &handlerIsInt, &handlerNotInt);
|
|
|
|
Bind(&handlerIsInt);
|
|
|
|
{
|
|
|
|
GateRef handlerInfo = TaggedCastToInt32(*handler);
|
|
|
|
Branch(IsField(handlerInfo), &handlerInfoIsField, &handlerInfoNotField);
|
|
|
|
Bind(&handlerInfoIsField);
|
|
|
|
{
|
|
|
|
StoreField(glue, receiver, value, handlerInfo);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&handlerInfoNotField);
|
|
|
|
{
|
|
|
|
GateRef accessor = LoadFromField(*holder, handlerInfo);
|
2022-05-30 02:41:07 +00:00
|
|
|
result = ChangeTaggedPointerToInt64(CallSetterHelper(glue, receiver, accessor, value));
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&handlerNotInt);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsTransitionHandler(*handler), &handlerIsTransitionHandler, &handlerNotTransitionHandler);
|
|
|
|
Bind(&handlerIsTransitionHandler);
|
|
|
|
{
|
|
|
|
StoreWithTransition(glue, receiver, value, *handler);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&handlerNotTransitionHandler);
|
|
|
|
{
|
2022-02-19 02:09:52 +00:00
|
|
|
Branch(TaggedIsPrototypeHandler(*handler), &handlerIsPrototypeHandler, &handlerNotPrototypeHandler);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&handlerNotPrototypeHandler);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsPropertyBox(*handler), &handlerIsPropertyBox, &handlerNotPropertyBox);
|
|
|
|
Bind(&handlerIsPropertyBox);
|
|
|
|
StoreGlobal(glue, value, *handler);
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(&handlerNotPropertyBox);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&handlerIsPrototypeHandler);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
GateRef cellValue = GetProtoCell(*handler);
|
2022-02-19 02:09:52 +00:00
|
|
|
Branch(GetHasChanged(cellValue), &cellHasChanged, &loopEnd);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&cellHasChanged);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Hole(VariableType::INT64());
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&loopEnd);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
holder = GetPrototypeHandlerHolder(*handler);
|
|
|
|
handler = GetPrototypeHandlerHandlerInfo(*handler);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::StoreField(GateRef glue, GateRef receiver, GateRef value, GateRef handler)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label handlerIsInlinedProperty(env);
|
|
|
|
Label handlerNotInlinedProperty(env);
|
|
|
|
GateRef index = HandlerBaseGetOffset(handler);
|
|
|
|
Branch(HandlerBaseIsInlinedProperty(handler), &handlerIsInlinedProperty, &handlerNotInlinedProperty);
|
|
|
|
Bind(&handlerIsInlinedProperty);
|
|
|
|
{
|
2022-03-01 08:31:08 +00:00
|
|
|
Store(VariableType::JS_ANY(), glue, receiver,
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())),
|
2021-12-17 09:18:10 +00:00
|
|
|
value);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&handlerNotInlinedProperty);
|
|
|
|
{
|
|
|
|
GateRef array = GetPropertiesArray(receiver);
|
2022-03-01 08:31:08 +00:00
|
|
|
SetValueToTaggedArray(VariableType::JS_ANY(), glue, array, index, value);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::StoreWithTransition(GateRef glue, GateRef receiver, GateRef value, GateRef handler)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
|
|
|
|
Label handlerInfoIsInlinedProps(env);
|
|
|
|
Label handlerInfoNotInlinedProps(env);
|
|
|
|
Label indexMoreCapacity(env);
|
|
|
|
Label indexLessCapacity(env);
|
|
|
|
GateRef newHClass = GetTransitionFromHClass(handler);
|
|
|
|
StoreHClass(glue, receiver, newHClass);
|
|
|
|
GateRef handlerInfo = TaggedCastToInt32(GetTransitionHandlerInfo(handler));
|
|
|
|
Branch(HandlerBaseIsInlinedProperty(handlerInfo), &handlerInfoIsInlinedProps, &handlerInfoNotInlinedProps);
|
|
|
|
Bind(&handlerInfoNotInlinedProps);
|
|
|
|
{
|
|
|
|
GateRef array = GetPropertiesArray(receiver);
|
2022-02-19 02:09:52 +00:00
|
|
|
GateRef capacity = GetLengthOfTaggedArray(array);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef index = HandlerBaseGetOffset(handlerInfo);
|
|
|
|
Branch(Int32GreaterThanOrEqual(index, capacity), &indexMoreCapacity, &indexLessCapacity);
|
|
|
|
Bind(&indexMoreCapacity);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
CallRuntime(glue,
|
|
|
|
RTSTUB_ID(PropertiesSetValue),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ receiver, value, array, IntToTaggedInt(capacity),
|
|
|
|
IntToTaggedInt(index) });
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&indexLessCapacity);
|
|
|
|
{
|
2022-05-20 09:24:45 +00:00
|
|
|
Store(VariableType::JS_ANY(), glue, PtrAdd(array, IntPtr(TaggedArray::DATA_OFFSET)),
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrMul(ChangeInt32ToIntPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())),
|
2021-12-17 09:18:10 +00:00
|
|
|
value);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&handlerInfoIsInlinedProps);
|
|
|
|
{
|
|
|
|
StoreField(glue, receiver, value, handlerInfo);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::StoreGlobal(GateRef glue, GateRef value, GateRef cell)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label cellIsInvalid(env);
|
|
|
|
Label cellNotInvalid(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2021-12-17 09:18:10 +00:00
|
|
|
Branch(IsInvalidPropertyBox(cell), &cellIsInvalid, &cellNotInvalid);
|
|
|
|
Bind(&cellIsInvalid);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&cellNotInvalid);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
Store(VariableType::JS_ANY(), glue, cell, IntPtr(PropertyBox::VALUE_OFFSET), value);
|
|
|
|
result = Undefined();
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-03-16 10:12:15 +00:00
|
|
|
template<typename DictionaryT>
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetAttributesFromDictionary(GateRef elements, GateRef entry)
|
2022-03-16 10:12:15 +00:00
|
|
|
{
|
|
|
|
GateRef arrayIndex =
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
|
|
|
|
Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
|
2022-03-16 10:12:15 +00:00
|
|
|
GateRef attributesIndex =
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_DETAILS_INDEX));
|
2022-03-16 10:12:15 +00:00
|
|
|
return TaggedCastToInt32(GetValueFromTaggedArray(VariableType::INT64(), elements, attributesIndex));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename DictionaryT>
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetValueFromDictionary(VariableType returnType, GateRef elements, GateRef entry)
|
2022-03-16 10:12:15 +00:00
|
|
|
{
|
|
|
|
GateRef arrayIndex =
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
|
|
|
|
Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
|
2022-03-16 10:12:15 +00:00
|
|
|
GateRef valueIndex =
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(arrayIndex, Int32(DictionaryT::ENTRY_VALUE_INDEX));
|
2022-03-16 10:12:15 +00:00
|
|
|
return GetValueFromTaggedArray(returnType, elements, valueIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename DictionaryT>
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetKeyFromDictionary(VariableType returnType, GateRef elements, GateRef entry)
|
2022-03-16 10:12:15 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subentry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subentry);
|
2022-03-16 10:12:15 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, returnType, Undefined());
|
2022-03-16 10:12:15 +00:00
|
|
|
Label ltZero(env);
|
|
|
|
Label notLtZero(env);
|
|
|
|
Label gtLength(env);
|
|
|
|
Label notGtLength(env);
|
|
|
|
GateRef dictionaryLength =
|
2022-03-31 09:26:17 +00:00
|
|
|
Load(VariableType::INT32(), elements, IntPtr(TaggedArray::LENGTH_OFFSET));
|
2022-03-16 10:12:15 +00:00
|
|
|
GateRef arrayIndex =
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(Int32(DictionaryT::TABLE_HEADER_SIZE),
|
|
|
|
Int32Mul(entry, Int32(DictionaryT::ENTRY_SIZE)));
|
|
|
|
Branch(Int32LessThan(arrayIndex, Int32(0)), <Zero, ¬LtZero);
|
2022-03-16 10:12:15 +00:00
|
|
|
Bind(<Zero);
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(¬LtZero);
|
|
|
|
Branch(Int32GreaterThan(arrayIndex, dictionaryLength), >Length, ¬GtLength);
|
|
|
|
Bind(>Length);
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(¬GtLength);
|
|
|
|
result = GetValueFromTaggedArray(returnType, elements, arrayIndex);
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-03-16 10:12:15 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-29 07:27:17 +00:00
|
|
|
inline void StubBuilder::UpdateValueAndAttributes(GateRef glue, GateRef elements, GateRef index,
|
|
|
|
GateRef value, GateRef attr)
|
2022-03-16 10:12:15 +00:00
|
|
|
{
|
|
|
|
GateRef arrayIndex =
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(Int32(NameDictionary::TABLE_HEADER_SIZE),
|
|
|
|
Int32Mul(index, Int32(NameDictionary::ENTRY_SIZE)));
|
2022-03-16 10:12:15 +00:00
|
|
|
GateRef valueIndex =
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_VALUE_INDEX));
|
2022-03-16 10:12:15 +00:00
|
|
|
GateRef attributesIndex =
|
2022-03-31 09:26:17 +00:00
|
|
|
Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_DETAILS_INDEX));
|
2022-03-16 10:12:15 +00:00
|
|
|
SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
|
|
|
|
GateRef attroffset =
|
2022-04-21 12:08:23 +00:00
|
|
|
PtrMul(ChangeInt32ToIntPtr(attributesIndex), IntPtr(JSTaggedValue::TaggedTypeSize()));
|
|
|
|
GateRef dataOffset = PtrAdd(attroffset, IntPtr(TaggedArray::DATA_OFFSET));
|
2022-08-29 07:10:59 +00:00
|
|
|
Store(VariableType::INT64(), glue, elements, dataOffset, IntToTaggedInt(attr));
|
2022-03-16 10:12:15 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
inline void StubBuilder::UpdateValueInDict(GateRef glue, GateRef elements, GateRef index, GateRef value)
|
2022-03-16 10:12:15 +00:00
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef arrayIndex = Int32Add(Int32(NameDictionary::TABLE_HEADER_SIZE),
|
|
|
|
Int32Mul(index, Int32(NameDictionary::ENTRY_SIZE)));
|
|
|
|
GateRef valueIndex = Int32Add(arrayIndex, Int32(NameDictionary::ENTRY_VALUE_INDEX));
|
2022-03-16 10:12:15 +00:00
|
|
|
SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, valueIndex, value);
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label loopExit(env);
|
|
|
|
Label afterLoop(env);
|
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
|
|
|
GateRef hclass = LoadHClass(*holder);
|
|
|
|
GateRef jsType = GetObjectType(hclass);
|
|
|
|
Label isSpecialIndexed(env);
|
|
|
|
Label notSpecialIndexed(env);
|
|
|
|
Branch(IsSpecialIndexedObj(jsType), &isSpecialIndexed, ¬SpecialIndexed);
|
|
|
|
Bind(&isSpecialIndexed);
|
|
|
|
{
|
2022-06-10 07:33:31 +00:00
|
|
|
// TypeArray
|
|
|
|
Label isFastTypeArray(env);
|
|
|
|
Label notFastTypeArray(env);
|
|
|
|
Branch(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
|
|
|
|
Bind(&isFastTypeArray);
|
|
|
|
{
|
|
|
|
result = CallRuntime(glue, RTSTUB_ID(GetTypeArrayPropertyByIndex),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ *holder, IntToTaggedInt(index), IntToTaggedInt(jsType)});
|
2022-06-10 07:33:31 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬FastTypeArray);
|
|
|
|
|
2022-01-04 11:30:40 +00:00
|
|
|
Label isSpecialContainer(env);
|
|
|
|
Label notSpecialContainer(env);
|
|
|
|
// Add SpecialContainer
|
|
|
|
Branch(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
|
|
|
|
Bind(&isSpecialContainer);
|
|
|
|
{
|
|
|
|
result = GetContainerProperty(glue, *holder, index, jsType);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬SpecialContainer);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Hole();
|
2022-01-04 11:30:40 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
Bind(¬SpecialIndexed);
|
|
|
|
{
|
|
|
|
GateRef elements = GetElementsArray(*holder);
|
|
|
|
Label isDictionaryElement(env);
|
|
|
|
Label notDictionaryElement(env);
|
|
|
|
Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
|
|
|
|
Bind(¬DictionaryElement);
|
|
|
|
{
|
|
|
|
Label lessThanLength(env);
|
|
|
|
Label notLessThanLength(env);
|
2022-04-21 12:08:23 +00:00
|
|
|
Branch(Int32UnsignedLessThan(index, GetLengthOfTaggedArray(elements)),
|
|
|
|
&lessThanLength, ¬LessThanLength);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&lessThanLength);
|
|
|
|
{
|
|
|
|
Label notHole(env);
|
|
|
|
Label isHole(env);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef value = GetValueFromTaggedArray(VariableType::JS_ANY(), elements, index);
|
2021-12-17 09:18:10 +00:00
|
|
|
Branch(TaggedIsNotHole(value), ¬Hole, &isHole);
|
|
|
|
Bind(¬Hole);
|
|
|
|
{
|
|
|
|
result = value;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&isHole);
|
|
|
|
{
|
|
|
|
Jump(&loopExit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬LessThanLength);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Hole();
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&isDictionaryElement);
|
|
|
|
{
|
2022-03-22 03:07:15 +00:00
|
|
|
GateRef entryA = FindElementFromNumberDictionary(glue, elements, index);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label notNegtiveOne(env);
|
|
|
|
Label negtiveOne(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32NotEqual(entryA, Int32(-1)), ¬NegtiveOne, &negtiveOne);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(¬NegtiveOne);
|
|
|
|
{
|
2022-03-22 03:07:15 +00:00
|
|
|
GateRef attr = GetAttributesFromDictionary<NumberDictionary>(elements, entryA);
|
|
|
|
GateRef value = GetValueFromDictionary<NumberDictionary>(VariableType::JS_ANY(), elements, entryA);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label isAccessor(env);
|
|
|
|
Label notAccessor(env);
|
|
|
|
Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
|
|
|
|
Bind(&isAccessor);
|
|
|
|
{
|
2022-05-30 02:41:07 +00:00
|
|
|
result = CallGetterHelper(glue, receiver, *holder, value);
|
|
|
|
Jump(&exit);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
Bind(¬Accessor);
|
|
|
|
{
|
|
|
|
result = value;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&negtiveOne);
|
|
|
|
Jump(&loopExit);
|
|
|
|
}
|
|
|
|
Bind(&loopExit);
|
|
|
|
{
|
|
|
|
holder = GetPrototypeFromHClass(LoadHClass(*holder));
|
|
|
|
Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&loopEnd);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
Bind(&afterLoop);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Undefined();
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetPropertyByValue(GateRef glue, GateRef receiver, GateRef keyValue)
|
2022-06-14 12:19:18 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
|
|
|
env->SubCfgEntry(&entry);
|
|
|
|
DEFVARIABLE(key, VariableType::JS_ANY(), keyValue);
|
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
|
|
|
Label isNumberOrStringSymbol(env);
|
|
|
|
Label notNumber(env);
|
|
|
|
Label isStringOrSymbol(env);
|
|
|
|
Label notStringOrSymbol(env);
|
|
|
|
Label exit(env);
|
|
|
|
|
|
|
|
Branch(TaggedIsNumber(*key), &isNumberOrStringSymbol, ¬Number);
|
|
|
|
Bind(¬Number);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsStringOrSymbol(*key), &isNumberOrStringSymbol, ¬StringOrSymbol);
|
|
|
|
Bind(¬StringOrSymbol);
|
|
|
|
{
|
|
|
|
result = Hole();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&isNumberOrStringSymbol);
|
|
|
|
{
|
|
|
|
GateRef index = TryToElementsIndex(*key);
|
|
|
|
Label validIndex(env);
|
|
|
|
Label notValidIndex(env);
|
|
|
|
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
|
|
|
|
Bind(&validIndex);
|
|
|
|
{
|
|
|
|
result = GetPropertyByIndex(glue, receiver, index);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬ValidIndex);
|
|
|
|
{
|
|
|
|
Label notNumber1(env);
|
|
|
|
Label getByName(env);
|
|
|
|
Branch(TaggedIsNumber(*key), &exit, ¬Number1);
|
|
|
|
Bind(¬Number1);
|
|
|
|
{
|
|
|
|
Label isString(env);
|
|
|
|
Label notString(env);
|
|
|
|
Label isInternalString(env);
|
|
|
|
Label notIntenalString(env);
|
|
|
|
Branch(TaggedIsString(*key), &isString, ¬String);
|
|
|
|
Bind(&isString);
|
|
|
|
{
|
|
|
|
Branch(IsInternalString(*key), &isInternalString, ¬IntenalString);
|
|
|
|
Bind(&isInternalString);
|
|
|
|
Jump(&getByName);
|
|
|
|
Bind(¬IntenalString);
|
|
|
|
{
|
|
|
|
key = CallRuntime(glue, RTSTUB_ID(NewInternalString), { *key });
|
|
|
|
Jump(&getByName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬String);
|
|
|
|
{
|
|
|
|
Jump(&getByName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&getByName);
|
|
|
|
{
|
|
|
|
result = GetPropertyByName(glue, receiver, *key);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetPropertyByName(GateRef glue, GateRef receiver, GateRef key)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label loopExit(env);
|
|
|
|
Label afterLoop(env);
|
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
|
|
|
GateRef hClass = LoadHClass(*holder);
|
|
|
|
GateRef jsType = GetObjectType(hClass);
|
|
|
|
Label isSIndexObj(env);
|
|
|
|
Label notSIndexObj(env);
|
|
|
|
Branch(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
|
|
|
|
Bind(&isSIndexObj);
|
|
|
|
{
|
2022-06-10 07:33:31 +00:00
|
|
|
// TypeArray
|
|
|
|
Label isFastTypeArray(env);
|
|
|
|
Label notFastTypeArray(env);
|
|
|
|
Branch(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
|
|
|
|
Bind(&isFastTypeArray);
|
|
|
|
{
|
|
|
|
result = GetTypeArrayPropertyByName(glue, receiver, *holder, key, jsType);
|
|
|
|
Label isNull(env);
|
|
|
|
Label notNull(env);
|
|
|
|
Branch(TaggedIsNull(*result), &isNull, ¬Null);
|
|
|
|
Bind(&isNull);
|
|
|
|
{
|
|
|
|
result = Hole();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Null);
|
|
|
|
Branch(TaggedIsHole(*result), ¬SIndexObj, &exit);
|
|
|
|
}
|
|
|
|
Bind(¬FastTypeArray);
|
|
|
|
{
|
|
|
|
result = Hole();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
Bind(¬SIndexObj);
|
|
|
|
{
|
|
|
|
Label isDicMode(env);
|
|
|
|
Label notDicMode(env);
|
|
|
|
Branch(IsDictionaryModeByHClass(hClass), &isDicMode, ¬DicMode);
|
|
|
|
Bind(¬DicMode);
|
|
|
|
{
|
|
|
|
GateRef layOutInfo = GetLayoutFromHClass(hClass);
|
|
|
|
GateRef propsNum = GetNumberOfPropsFromHClass(hClass);
|
2022-03-22 03:07:15 +00:00
|
|
|
// int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
|
|
|
|
GateRef entryA = FindElementWithCache(glue, layOutInfo, hClass, key, propsNum);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label hasEntry(env);
|
|
|
|
Label noEntry(env);
|
2022-03-22 03:07:15 +00:00
|
|
|
// if branch condition : entry != -1
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32NotEqual(entryA, Int32(-1)), &hasEntry, &noEntry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&hasEntry);
|
|
|
|
{
|
2022-03-22 03:07:15 +00:00
|
|
|
// PropertyAttributes attr(layoutInfo->GetAttr(entry))
|
|
|
|
GateRef propAttr = GetPropAttrFromLayoutInfo(layOutInfo, entryA);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef attr = TaggedCastToInt32(propAttr);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef value = JSObjectGetProperty(VariableType::JS_ANY(), *holder, hClass, attr);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label isAccessor(env);
|
|
|
|
Label notAccessor(env);
|
|
|
|
Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
|
|
|
|
Bind(&isAccessor);
|
|
|
|
{
|
2022-05-30 02:41:07 +00:00
|
|
|
result = CallGetterHelper(glue, receiver, *holder, value);
|
|
|
|
Jump(&exit);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
Bind(¬Accessor);
|
|
|
|
{
|
|
|
|
result = value;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&noEntry);
|
|
|
|
{
|
|
|
|
Jump(&loopExit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&isDicMode);
|
|
|
|
{
|
|
|
|
GateRef array = GetPropertiesArray(*holder);
|
2022-03-22 03:07:15 +00:00
|
|
|
// int entry = dict->FindEntry(key)
|
|
|
|
GateRef entryB = FindEntryFromNameDictionary(glue, array, key);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label notNegtiveOne(env);
|
|
|
|
Label negtiveOne(env);
|
2022-03-22 03:07:15 +00:00
|
|
|
// if branch condition : entry != -1
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32NotEqual(entryB, Int32(-1)), ¬NegtiveOne, &negtiveOne);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(¬NegtiveOne);
|
|
|
|
{
|
2022-03-22 03:07:15 +00:00
|
|
|
// auto value = dict->GetValue(entry)
|
|
|
|
GateRef attr = GetAttributesFromDictionary<NameDictionary>(array, entryB);
|
|
|
|
// auto attr = dict->GetAttributes(entry)
|
|
|
|
GateRef value = GetValueFromDictionary<NameDictionary>(VariableType::JS_ANY(), array, entryB);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label isAccessor1(env);
|
|
|
|
Label notAccessor1(env);
|
|
|
|
Branch(IsAccessor(attr), &isAccessor1, ¬Accessor1);
|
|
|
|
Bind(&isAccessor1);
|
|
|
|
{
|
2022-05-30 02:41:07 +00:00
|
|
|
result = CallGetterHelper(glue, receiver, *holder, value);
|
|
|
|
Jump(&exit);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
Bind(¬Accessor1);
|
|
|
|
{
|
|
|
|
result = value;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&negtiveOne);
|
|
|
|
Jump(&loopExit);
|
|
|
|
}
|
|
|
|
Bind(&loopExit);
|
|
|
|
{
|
|
|
|
holder = GetPrototypeFromHClass(LoadHClass(*holder));
|
|
|
|
Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&loopEnd);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
Bind(&afterLoop);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Undefined();
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::CopyAllHClass(GateRef glue, GateRef dstHClass, GateRef srcHClass)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
auto proto = GetPrototypeFromHClass(srcHClass);
|
2022-03-02 09:11:35 +00:00
|
|
|
SetPrototypeToHClass(VariableType::JS_POINTER(), glue, dstHClass, proto);
|
2021-12-17 09:18:10 +00:00
|
|
|
SetBitFieldToHClass(glue, dstHClass, GetBitFieldFromHClass(srcHClass));
|
2021-12-31 07:51:09 +00:00
|
|
|
SetNumberOfPropsToHClass(glue, dstHClass, GetNumberOfPropsFromHClass(srcHClass));
|
2022-03-31 09:26:17 +00:00
|
|
|
SetTransitionsToHClass(VariableType::INT64(), glue, dstHClass, Int64(JSTaggedValue::VALUE_UNDEFINED));
|
2022-03-01 08:31:08 +00:00
|
|
|
SetProtoChangeDetailsToHClass(VariableType::INT64(), glue, dstHClass,
|
2022-03-31 09:26:17 +00:00
|
|
|
Int64(JSTaggedValue::VALUE_NULL));
|
|
|
|
SetEnumCacheToHClass(VariableType::INT64(), glue, dstHClass, Int64(JSTaggedValue::VALUE_NULL));
|
2022-03-02 09:11:35 +00:00
|
|
|
SetLayoutToHClass(VariableType::JS_POINTER(), glue, dstHClass, GetLayoutFromHClass(srcHClass));
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FindTransitions(GateRef glue, GateRef receiver, GateRef hclass, GateRef key, GateRef metaData)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef transitionOffset = IntPtr(JSHClass::TRANSTIONS_OFFSET);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef transition = Load(VariableType::JS_POINTER(), hclass, transitionOffset);
|
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), transition);
|
2021-12-17 09:18:10 +00:00
|
|
|
|
2022-03-11 09:30:43 +00:00
|
|
|
Label notUndefined(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int64Equal(transition, Undefined()), &exit, ¬Undefined);
|
2022-03-11 09:30:43 +00:00
|
|
|
Bind(¬Undefined);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-03-11 09:30:43 +00:00
|
|
|
Label isWeak(env);
|
|
|
|
Label notWeak(env);
|
|
|
|
Branch(TaggedIsWeak(transition), &isWeak, ¬Weak);
|
|
|
|
Bind(&isWeak);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-03-11 09:30:43 +00:00
|
|
|
GateRef transitionHClass = TaggedCastToWeakReferentUnChecked(transition);
|
|
|
|
GateRef propNums = GetNumberOfPropsFromHClass(transitionHClass);
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef last = Int32Sub(propNums, Int32(1));
|
2022-03-11 09:30:43 +00:00
|
|
|
GateRef layoutInfo = GetLayoutFromHClass(transitionHClass);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef cachedKey = GetKeyFromLayoutInfo(layoutInfo, last);
|
|
|
|
GateRef cachedAttr = TaggedCastToInt32(GetPropAttrFromLayoutInfo(layoutInfo, last));
|
|
|
|
GateRef cachedMetaData = GetPropertyMetaDataFromAttr(cachedAttr);
|
|
|
|
Label keyMatch(env);
|
|
|
|
Label isMatch(env);
|
|
|
|
Label notMatch(env);
|
2022-02-08 09:22:08 +00:00
|
|
|
Branch(Int64Equal(cachedKey, key), &keyMatch, ¬Match);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&keyMatch);
|
|
|
|
{
|
2022-02-08 09:22:08 +00:00
|
|
|
Branch(Int32Equal(metaData, cachedMetaData), &isMatch, ¬Match);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&isMatch);
|
|
|
|
{
|
|
|
|
#if ECMASCRIPT_ENABLE_IC
|
2022-03-11 09:30:43 +00:00
|
|
|
NotifyHClassChanged(glue, hclass, transitionHClass);
|
2021-12-17 09:18:10 +00:00
|
|
|
#endif
|
2022-03-11 09:30:43 +00:00
|
|
|
StoreHClass(glue, receiver, transitionHClass);
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬Match);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Undefined();
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
2022-03-11 09:30:43 +00:00
|
|
|
Bind(¬Weak);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
// need to find from dictionary
|
2022-03-22 03:07:15 +00:00
|
|
|
GateRef entryA = FindEntryFromTransitionDictionary(glue, transition, key, metaData);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label isFound(env);
|
|
|
|
Label notFound(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32NotEqual(entryA, Int32(-1)), &isFound, ¬Found);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&isFound);
|
2022-03-11 09:30:43 +00:00
|
|
|
auto value = GetValueFromDictionary<TransitionsDictionary>(
|
2022-03-22 03:07:15 +00:00
|
|
|
VariableType::JS_POINTER(), transition, entryA);
|
2022-03-11 09:30:43 +00:00
|
|
|
Label valueUndefined(env);
|
|
|
|
Label valueNotUndefined(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int64NotEqual(value, Undefined()), &valueNotUndefined,
|
2022-03-11 09:30:43 +00:00
|
|
|
&valueUndefined);
|
|
|
|
Bind(&valueNotUndefined);
|
|
|
|
{
|
|
|
|
GateRef newHClass = TaggedCastToWeakReferentUnChecked(value);
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(newHClass);
|
2021-12-17 09:18:10 +00:00
|
|
|
#if ECMASCRIPT_ENABLE_IC
|
2022-03-11 09:30:43 +00:00
|
|
|
NotifyHClassChanged(glue, hclass, newHClass);
|
2021-12-17 09:18:10 +00:00
|
|
|
#endif
|
2022-03-11 09:30:43 +00:00
|
|
|
StoreHClass(glue, receiver, newHClass);
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(¬Found);
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Undefined();
|
2022-03-11 09:30:43 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&valueUndefined);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Undefined();
|
2022-03-11 09:30:43 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(returnValue, VariableType::INT64(), Hole(VariableType::INT64()));
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(holder, VariableType::JS_ANY(), receiver);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
2022-04-07 13:45:47 +00:00
|
|
|
Label ifEnd(env);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label loopExit(env);
|
|
|
|
Label afterLoop(env);
|
2022-04-07 13:45:47 +00:00
|
|
|
if (!useOwn) {
|
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
}
|
|
|
|
GateRef hclass = LoadHClass(*holder);
|
|
|
|
GateRef jsType = GetObjectType(hclass);
|
|
|
|
Label isSpecialIndex(env);
|
|
|
|
Label notSpecialIndex(env);
|
|
|
|
Branch(IsSpecialIndexedObj(jsType), &isSpecialIndex, ¬SpecialIndex);
|
|
|
|
Bind(&isSpecialIndex);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-06-10 07:33:31 +00:00
|
|
|
// TypeArray
|
|
|
|
Label isFastTypeArray(env);
|
|
|
|
Label notFastTypeArray(env);
|
|
|
|
Branch(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
|
|
|
|
Bind(&isFastTypeArray);
|
|
|
|
{
|
|
|
|
returnValue = ChangeTaggedPointerToInt64(CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType)}));
|
2022-06-10 07:33:31 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬FastTypeArray);
|
2022-04-07 13:45:47 +00:00
|
|
|
returnValue = Hole(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬SpecialIndex);
|
|
|
|
{
|
|
|
|
GateRef elements = GetElementsArray(*holder);
|
|
|
|
Label isDictionaryElement(env);
|
|
|
|
Label notDictionaryElement(env);
|
|
|
|
Branch(IsDictionaryElement(hclass), &isDictionaryElement, ¬DictionaryElement);
|
|
|
|
Bind(¬DictionaryElement);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-07 13:45:47 +00:00
|
|
|
Label isReceiver(env);
|
|
|
|
if (useOwn) {
|
|
|
|
Branch(Int64Equal(*holder, receiver), &isReceiver, &ifEnd);
|
|
|
|
} else {
|
|
|
|
Branch(Int64Equal(*holder, receiver), &isReceiver, &afterLoop);
|
|
|
|
}
|
|
|
|
Bind(&isReceiver);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-07 13:45:47 +00:00
|
|
|
GateRef length = GetLengthOfTaggedArray(elements);
|
|
|
|
Label inRange(env);
|
|
|
|
if (useOwn) {
|
|
|
|
Branch(Int64LessThan(index, length), &inRange, &ifEnd);
|
|
|
|
} else {
|
2022-02-08 09:22:08 +00:00
|
|
|
Branch(Int64LessThan(index, length), &inRange, &loopExit);
|
2022-04-07 13:45:47 +00:00
|
|
|
}
|
|
|
|
Bind(&inRange);
|
|
|
|
{
|
|
|
|
GateRef value1 = GetValueFromTaggedArray(VariableType::JS_ANY(), elements, index);
|
|
|
|
Label notHole(env);
|
|
|
|
if (useOwn) {
|
|
|
|
Branch(Int64NotEqual(value1, Hole()), ¬Hole, &ifEnd);
|
|
|
|
} else {
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int64NotEqual(value1, Hole()), ¬Hole, &loopExit);
|
2022-04-07 13:45:47 +00:00
|
|
|
}
|
|
|
|
Bind(¬Hole);
|
|
|
|
{
|
|
|
|
SetValueToTaggedArray(VariableType::JS_ANY(), glue, elements, index, value);
|
|
|
|
returnValue = Undefined(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
}
|
|
|
|
Bind(&isDictionaryElement);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
returnValue = Hole(VariableType::INT64());
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
}
|
|
|
|
if (useOwn) {
|
|
|
|
Bind(&ifEnd);
|
|
|
|
} else {
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&loopExit);
|
|
|
|
{
|
|
|
|
holder = GetPrototypeFromHClass(LoadHClass(*holder));
|
|
|
|
Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
|
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
Bind(&loopEnd);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
Bind(&afterLoop);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
Label isExtensible(env);
|
|
|
|
Label notExtensible(env);
|
|
|
|
Branch(IsExtensible(receiver), &isExtensible, ¬Extensible);
|
|
|
|
Bind(&isExtensible);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-07 13:45:47 +00:00
|
|
|
GateRef result = CallRuntime(glue, RTSTUB_ID(AddElementInternal),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ receiver, IntToTaggedInt(index), value,
|
|
|
|
IntToTaggedInt(Int32(PropertyAttributes::GetDefaultAttributes())) });
|
2022-04-07 13:45:47 +00:00
|
|
|
Label success(env);
|
|
|
|
Label failed(env);
|
|
|
|
Branch(TaggedIsTrue(result), &success, &failed);
|
|
|
|
Bind(&success);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
returnValue = Undefined(VariableType::INT64());
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
Bind(&failed);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
returnValue = Exception(VariableType::INT64());
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
Bind(¬Extensible);
|
|
|
|
{
|
|
|
|
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
|
2022-08-29 07:10:59 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
|
2022-04-07 13:45:47 +00:00
|
|
|
returnValue = Exception(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *returnValue;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value, bool useOwn)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
2022-01-11 13:09:24 +00:00
|
|
|
Label entryPass(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entryPass);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::INT64(), Hole(VariableType::INT64()));
|
2022-03-01 08:31:08 +00:00
|
|
|
DEFVARIABLE(holder, VariableType::JS_POINTER(), receiver);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
2022-04-07 13:45:47 +00:00
|
|
|
Label ifEnd(env);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label loopExit(env);
|
|
|
|
Label afterLoop(env);
|
2022-04-07 13:45:47 +00:00
|
|
|
if (!useOwn) {
|
|
|
|
// a do-while loop
|
|
|
|
Jump(&loopHead);
|
|
|
|
LoopBegin(&loopHead);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
// auto *hclass = holder.GetTaggedObject()->GetClass()
|
|
|
|
// JSType jsType = hclass->GetObjectType()
|
|
|
|
GateRef hClass = LoadHClass(*holder);
|
|
|
|
GateRef jsType = GetObjectType(hClass);
|
|
|
|
Label isSIndexObj(env);
|
|
|
|
Label notSIndexObj(env);
|
|
|
|
// if branch condition : IsSpecialIndexedObj(jsType)
|
|
|
|
Branch(IsSpecialIndexedObj(jsType), &isSIndexObj, ¬SIndexObj);
|
|
|
|
Bind(&isSIndexObj);
|
2022-01-04 11:30:40 +00:00
|
|
|
{
|
2022-06-10 07:33:31 +00:00
|
|
|
Label isFastTypeArray(env);
|
|
|
|
Label notFastTypeArray(env);
|
|
|
|
Branch(IsFastTypeArray(jsType), &isFastTypeArray, ¬FastTypeArray);
|
|
|
|
Bind(&isFastTypeArray);
|
|
|
|
{
|
|
|
|
result =
|
|
|
|
ChangeTaggedPointerToInt64(SetTypeArrayPropertyByName(glue, receiver, *holder, key, value, jsType));
|
|
|
|
Label isNull(env);
|
|
|
|
Label notNull(env);
|
|
|
|
Branch(TaggedIsNull(*result), &isNull, ¬Null);
|
|
|
|
Bind(&isNull);
|
|
|
|
{
|
|
|
|
result = Hole(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Null);
|
|
|
|
Branch(TaggedIsHole(*result), ¬SIndexObj, &exit);
|
|
|
|
}
|
|
|
|
Bind(¬FastTypeArray);
|
|
|
|
|
2022-01-04 11:30:40 +00:00
|
|
|
Label isSpecialContainer(env);
|
|
|
|
Label notSpecialContainer(env);
|
|
|
|
// Add SpecialContainer
|
|
|
|
Branch(IsSpecialContainer(jsType), &isSpecialContainer, ¬SpecialContainer);
|
|
|
|
Bind(&isSpecialContainer);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotSetPropertyOnContainer));
|
2022-08-29 07:10:59 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Exception(VariableType::INT64());
|
2022-01-04 11:30:40 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬SpecialContainer);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Hole(VariableType::INT64());
|
2022-01-04 11:30:40 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(¬SIndexObj);
|
|
|
|
{
|
|
|
|
Label isDicMode(env);
|
|
|
|
Label notDicMode(env);
|
|
|
|
// if branch condition : LIKELY(!hclass->IsDictionaryMode())
|
|
|
|
Branch(IsDictionaryModeByHClass(hClass), &isDicMode, ¬DicMode);
|
|
|
|
Bind(¬DicMode);
|
|
|
|
{
|
|
|
|
// LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetAttributes().GetTaggedObject())
|
|
|
|
GateRef layOutInfo = GetLayoutFromHClass(hClass);
|
|
|
|
// int propsNumber = hclass->NumberOfPropsFromHClass()
|
|
|
|
GateRef propsNum = GetNumberOfPropsFromHClass(hClass);
|
|
|
|
// int entry = layoutInfo->FindElementWithCache(thread, hclass, key, propsNumber)
|
2022-04-07 13:45:47 +00:00
|
|
|
GateRef entry = FindElementWithCache(glue, layOutInfo, hClass, key, propsNum);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label hasEntry(env);
|
|
|
|
// if branch condition : entry != -1
|
2022-04-07 13:45:47 +00:00
|
|
|
if (useOwn) {
|
|
|
|
Branch(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
|
|
|
|
} else {
|
|
|
|
Branch(Int32NotEqual(entry, Int32(-1)), &hasEntry, &loopExit);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&hasEntry);
|
|
|
|
{
|
|
|
|
// PropertyAttributes attr(layoutInfo->GetAttr(entry))
|
2022-04-07 13:45:47 +00:00
|
|
|
GateRef propAttr = GetPropAttrFromLayoutInfo(layOutInfo, entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef attr = TaggedCastToInt32(propAttr);
|
|
|
|
Label isAccessor(env);
|
|
|
|
Label notAccessor(env);
|
|
|
|
Branch(IsAccessor(attr), &isAccessor, ¬Accessor);
|
|
|
|
Bind(&isAccessor);
|
|
|
|
{
|
|
|
|
// auto accessor = JSObject::Cast(holder)->GetProperty(hclass, attr)
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef accessor = JSObjectGetProperty(VariableType::JS_ANY(), *holder, hClass, attr);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label shouldCall(env);
|
|
|
|
// ShouldCallSetter(receiver, *holder, accessor, attr)
|
2022-04-07 13:45:47 +00:00
|
|
|
Branch(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, ¬Accessor);
|
|
|
|
Bind(&shouldCall);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-05-30 02:41:07 +00:00
|
|
|
result = ChangeTaggedPointerToInt64(CallSetterHelper(glue, receiver, accessor, value));
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬Accessor);
|
|
|
|
{
|
|
|
|
Label writable(env);
|
|
|
|
Label notWritable(env);
|
|
|
|
Branch(IsWritable(attr), &writable, ¬Writable);
|
2022-04-07 13:45:47 +00:00
|
|
|
Bind(¬Writable);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-07 13:45:47 +00:00
|
|
|
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
|
2022-08-29 07:10:59 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Exception(VariableType::INT64());
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
Bind(&writable);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
Label holdEqualsRecv(env);
|
2022-04-07 13:45:47 +00:00
|
|
|
if (useOwn) {
|
|
|
|
Branch(Int64Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
|
|
|
|
} else {
|
|
|
|
Branch(Int64Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
|
|
|
|
}
|
|
|
|
Bind(&holdEqualsRecv);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-07 13:45:47 +00:00
|
|
|
// JSObject::Cast(holder)->SetProperty(thread, hclass, attr, value)
|
|
|
|
// return JSTaggedValue::Undefined()
|
|
|
|
JSObjectSetProperty(glue, *holder, hClass, attr, value);
|
|
|
|
result = Undefined(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&isDicMode);
|
|
|
|
{
|
|
|
|
GateRef array = GetPropertiesArray(*holder);
|
|
|
|
// int entry = dict->FindEntry(key)
|
|
|
|
GateRef entry1 = FindEntryFromNameDictionary(glue, array, key);
|
|
|
|
Label notNegtiveOne(env);
|
|
|
|
// if branch condition : entry != -1
|
2022-04-07 13:45:47 +00:00
|
|
|
if (useOwn) {
|
|
|
|
Branch(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &ifEnd);
|
|
|
|
} else {
|
|
|
|
Branch(Int32NotEqual(entry1, Int32(-1)), ¬NegtiveOne, &loopExit);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(¬NegtiveOne);
|
|
|
|
{
|
|
|
|
// auto attr = dict->GetAttributes(entry)
|
2022-03-16 10:12:15 +00:00
|
|
|
GateRef attr1 = GetAttributesFromDictionary<NameDictionary>(array, entry1);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label isAccessor1(env);
|
|
|
|
Label notAccessor1(env);
|
|
|
|
// if branch condition : UNLIKELY(attr.IsAccessor())
|
|
|
|
Branch(IsAccessor(attr1), &isAccessor1, ¬Accessor1);
|
|
|
|
Bind(&isAccessor1);
|
|
|
|
{
|
|
|
|
// auto accessor = dict->GetValue(entry)
|
2022-04-07 13:45:47 +00:00
|
|
|
GateRef accessor1 = GetValueFromDictionary<NameDictionary>(VariableType::JS_ANY(),
|
|
|
|
array, entry1);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label shouldCall1(env);
|
2022-04-07 13:45:47 +00:00
|
|
|
Branch(ShouldCallSetter(receiver, *holder, accessor1, attr1), &shouldCall1, ¬Accessor1);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(&shouldCall1);
|
2022-04-07 13:45:47 +00:00
|
|
|
{
|
2022-05-30 02:41:07 +00:00
|
|
|
result = ChangeTaggedPointerToInt64(CallSetterHelper(glue, receiver, accessor1, value));
|
2022-04-07 13:45:47 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
Bind(¬Accessor1);
|
|
|
|
{
|
|
|
|
Label writable1(env);
|
|
|
|
Label notWritable1(env);
|
|
|
|
Branch(IsWritable(attr1), &writable1, ¬Writable1);
|
2022-04-07 13:45:47 +00:00
|
|
|
Bind(¬Writable1);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-07 13:45:47 +00:00
|
|
|
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
|
2022-08-29 07:10:59 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Exception(VariableType::INT64());
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
Bind(&writable1);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
Label holdEqualsRecv1(env);
|
2022-04-07 13:45:47 +00:00
|
|
|
if (useOwn) {
|
|
|
|
Branch(Int64Equal(*holder, receiver), &holdEqualsRecv1, &ifEnd);
|
|
|
|
} else {
|
|
|
|
Branch(Int64Equal(*holder, receiver), &holdEqualsRecv1, &afterLoop);
|
|
|
|
}
|
|
|
|
Bind(&holdEqualsRecv1);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-07 13:45:47 +00:00
|
|
|
// dict->UpdateValue(thread, entry, value)
|
|
|
|
// return JSTaggedValue::Undefined()
|
|
|
|
UpdateValueInDict(glue, array, entry1, value);
|
|
|
|
result = Undefined(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
if (useOwn) {
|
|
|
|
Bind(&ifEnd);
|
|
|
|
} else {
|
|
|
|
Bind(&loopExit);
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
2022-04-07 13:45:47 +00:00
|
|
|
// holder = hclass->GetPrototype()
|
|
|
|
holder = GetPrototypeFromHClass(LoadHClass(*holder));
|
|
|
|
// loop condition for a do-while loop
|
|
|
|
Branch(TaggedIsHeapObject(*holder), &loopEnd, &afterLoop);
|
2021-12-17 09:18:10 +00:00
|
|
|
}
|
2022-04-07 13:45:47 +00:00
|
|
|
Bind(&loopEnd);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
Bind(&afterLoop);
|
|
|
|
}
|
|
|
|
Label extensible(env);
|
|
|
|
Label inextensible(env);
|
|
|
|
Branch(IsExtensible(receiver), &extensible, &inextensible);
|
|
|
|
Bind(&inextensible);
|
|
|
|
{
|
|
|
|
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetPropertyWhenNotExtensible));
|
2022-08-29 07:10:59 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
|
2022-04-07 13:45:47 +00:00
|
|
|
result = Exception(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&extensible);
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
result = AddPropertyByName(glue, receiver, key, value,
|
2022-04-07 13:45:47 +00:00
|
|
|
Int32(PropertyAttributes::GetDefaultAttributes()));
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, bool useOwn)
|
2022-04-07 13:45:47 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subEntry1(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&subEntry1);
|
2022-04-07 13:45:47 +00:00
|
|
|
DEFVARIABLE(varKey, VariableType::JS_ANY(), key);
|
|
|
|
DEFVARIABLE(result, VariableType::INT64(), Hole(VariableType::INT64()));
|
|
|
|
Label isNumberOrStringSymbol(env);
|
|
|
|
Label notNumber(env);
|
|
|
|
Label isStringOrSymbol(env);
|
|
|
|
Label notStringOrSymbol(env);
|
|
|
|
Label exit(env);
|
|
|
|
Branch(TaggedIsNumber(*varKey), &isNumberOrStringSymbol, ¬Number);
|
|
|
|
Bind(¬Number);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsStringOrSymbol(*varKey), &isNumberOrStringSymbol, ¬StringOrSymbol);
|
|
|
|
Bind(¬StringOrSymbol);
|
|
|
|
{
|
|
|
|
result = Hole(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&isNumberOrStringSymbol);
|
|
|
|
{
|
|
|
|
GateRef index = TryToElementsIndex(*varKey);
|
|
|
|
Label validIndex(env);
|
|
|
|
Label notValidIndex(env);
|
|
|
|
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
|
|
|
|
Bind(&validIndex);
|
|
|
|
{
|
|
|
|
result = SetPropertyByIndex(glue, receiver, index, value, useOwn);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬ValidIndex);
|
|
|
|
{
|
|
|
|
Label isNumber1(env);
|
|
|
|
Label notNumber1(env);
|
|
|
|
Label setByName(env);
|
|
|
|
Branch(TaggedIsNumber(*varKey), &isNumber1, ¬Number1);
|
|
|
|
Bind(&isNumber1);
|
|
|
|
{
|
|
|
|
result = Hole(VariableType::INT64());
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Number1);
|
|
|
|
{
|
|
|
|
Label isString(env);
|
|
|
|
Label notIntenalString(env);
|
|
|
|
Branch(TaggedIsString(*varKey), &isString, &setByName);
|
|
|
|
Bind(&isString);
|
|
|
|
{
|
|
|
|
Branch(IsInternalString(*varKey), &setByName, ¬IntenalString);
|
|
|
|
Bind(¬IntenalString);
|
|
|
|
{
|
|
|
|
varKey = CallRuntime(glue, RTSTUB_ID(NewInternalString), { *varKey });
|
|
|
|
Jump(&setByName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&setByName);
|
|
|
|
{
|
|
|
|
result = SetPropertyByName(glue, receiver, *varKey, value, useOwn);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-04-07 13:45:47 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::NotifyHClassChanged(GateRef glue, GateRef oldHClass, GateRef newHClass)
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2021-12-17 09:18:10 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label isProtoType(env);
|
|
|
|
Branch(IsProtoTypeHClass(oldHClass), &isProtoType, &exit);
|
|
|
|
Bind(&isProtoType);
|
|
|
|
{
|
|
|
|
Label notEqualHClass(env);
|
2022-02-08 09:22:08 +00:00
|
|
|
Branch(Int64Equal(oldHClass, newHClass), &exit, ¬EqualHClass);
|
2021-12-17 09:18:10 +00:00
|
|
|
Bind(¬EqualHClass);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
SetIsProtoTypeToHClass(glue, newHClass, True());
|
|
|
|
CallRuntime(glue, RTSTUB_ID(NoticeThroughChainAndRefreshUser), { oldHClass, newHClass });
|
2021-12-17 09:18:10 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2021-12-17 09:18:10 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-01-04 11:30:40 +00:00
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetContainerProperty(GateRef glue, GateRef receiver, GateRef index, GateRef jsType)
|
2022-01-04 11:30:40 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-01-04 11:30:40 +00:00
|
|
|
Label exit(env);
|
2022-06-16 03:01:51 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2022-01-04 11:30:40 +00:00
|
|
|
|
2022-05-23 01:49:27 +00:00
|
|
|
Label isDefaultLabel(env);
|
|
|
|
Label noDefaultLabel(env);
|
|
|
|
Branch(IsSpecialContainer(jsType), &noDefaultLabel, &isDefaultLabel);
|
|
|
|
Bind(&noDefaultLabel);
|
2022-01-04 11:30:40 +00:00
|
|
|
{
|
2022-05-23 01:49:27 +00:00
|
|
|
result = JSAPIContainerGet(glue, receiver, index);
|
2022-01-04 11:30:40 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-05-23 01:49:27 +00:00
|
|
|
Bind(&isDefaultLabel);
|
2022-01-04 11:30:40 +00:00
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2022-05-23 01:49:27 +00:00
|
|
|
|
2022-01-04 11:30:40 +00:00
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-01-04 11:30:40 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastTypeOf(GateRef glue, GateRef obj)
|
2022-03-14 03:50:02 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-14 03:50:02 +00:00
|
|
|
Label exit(env);
|
|
|
|
|
2022-04-21 12:08:23 +00:00
|
|
|
GateRef gConstAddr = PtrAdd(glue,
|
2022-04-06 06:26:53 +00:00
|
|
|
IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit())));
|
|
|
|
GateRef undefinedIndex = GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX);
|
|
|
|
GateRef gConstUndefinedStr = Load(VariableType::JS_POINTER(), gConstAddr, undefinedIndex);
|
|
|
|
DEFVARIABLE(result, VariableType::JS_POINTER(), gConstUndefinedStr);
|
2022-03-14 03:50:02 +00:00
|
|
|
Label objIsTrue(env);
|
|
|
|
Label objNotTrue(env);
|
|
|
|
Label defaultLabel(env);
|
2022-04-06 06:26:53 +00:00
|
|
|
GateRef gConstBooleanStr = Load(VariableType::JS_POINTER(), gConstAddr,
|
|
|
|
GetGlobalConstantString(ConstantIndex::BOOLEAN_STRING_INDEX));
|
|
|
|
Branch(TaggedIsTrue(obj), &objIsTrue, &objNotTrue);
|
2022-03-14 03:50:02 +00:00
|
|
|
Bind(&objIsTrue);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
result = gConstBooleanStr;
|
2022-03-14 03:50:02 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotTrue);
|
|
|
|
{
|
|
|
|
Label objIsFalse(env);
|
|
|
|
Label objNotFalse(env);
|
2022-04-06 06:26:53 +00:00
|
|
|
Branch(TaggedIsFalse(obj), &objIsFalse, &objNotFalse);
|
2022-03-14 03:50:02 +00:00
|
|
|
Bind(&objIsFalse);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
result = gConstBooleanStr;
|
2022-03-14 03:50:02 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotFalse);
|
|
|
|
{
|
|
|
|
Label objIsNull(env);
|
|
|
|
Label objNotNull(env);
|
2022-04-06 06:26:53 +00:00
|
|
|
Branch(TaggedIsNull(obj), &objIsNull, &objNotNull);
|
2022-03-14 03:50:02 +00:00
|
|
|
Bind(&objIsNull);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
result = Load(VariableType::JS_POINTER(), gConstAddr,
|
2022-03-14 03:50:02 +00:00
|
|
|
GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotNull);
|
|
|
|
{
|
|
|
|
Label objIsUndefined(env);
|
|
|
|
Label objNotUndefined(env);
|
2022-04-06 06:26:53 +00:00
|
|
|
Branch(TaggedIsUndefined(obj), &objIsUndefined, &objNotUndefined);
|
2022-03-14 03:50:02 +00:00
|
|
|
Bind(&objIsUndefined);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
result = Load(VariableType::JS_POINTER(), gConstAddr,
|
2022-03-14 03:50:02 +00:00
|
|
|
GetGlobalConstantString(ConstantIndex::UNDEFINED_STRING_INDEX));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotUndefined);
|
|
|
|
Jump(&defaultLabel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&defaultLabel);
|
|
|
|
{
|
|
|
|
Label objIsHeapObject(env);
|
|
|
|
Label objNotHeapObject(env);
|
|
|
|
Branch(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotHeapObject);
|
|
|
|
Bind(&objIsHeapObject);
|
|
|
|
{
|
|
|
|
Label objIsString(env);
|
|
|
|
Label objNotString(env);
|
|
|
|
Branch(IsString(obj), &objIsString, &objNotString);
|
|
|
|
Bind(&objIsString);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
result = Load(VariableType::JS_POINTER(), gConstAddr,
|
2022-03-14 03:50:02 +00:00
|
|
|
GetGlobalConstantString(ConstantIndex::STRING_STRING_INDEX));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotString);
|
|
|
|
{
|
|
|
|
Label objIsSymbol(env);
|
|
|
|
Label objNotSymbol(env);
|
|
|
|
Branch(IsSymbol(obj), &objIsSymbol, &objNotSymbol);
|
|
|
|
Bind(&objIsSymbol);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
result = Load(VariableType::JS_POINTER(), gConstAddr,
|
2022-03-14 03:50:02 +00:00
|
|
|
GetGlobalConstantString(ConstantIndex::SYMBOL_STRING_INDEX));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotSymbol);
|
|
|
|
{
|
|
|
|
Label objIsCallable(env);
|
|
|
|
Label objNotCallable(env);
|
|
|
|
Branch(IsCallable(obj), &objIsCallable, &objNotCallable);
|
|
|
|
Bind(&objIsCallable);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
result = Load(VariableType::JS_POINTER(), gConstAddr,
|
2022-03-14 03:50:02 +00:00
|
|
|
GetGlobalConstantString(ConstantIndex::FUNCTION_STRING_INDEX));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotCallable);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
Label objIsBigInt(env);
|
|
|
|
Label objNotBigInt(env);
|
2022-07-30 03:49:38 +00:00
|
|
|
Branch(TaggedObjectIsBigInt(obj), &objIsBigInt, &objNotBigInt);
|
2022-04-06 06:26:53 +00:00
|
|
|
Bind(&objIsBigInt);
|
|
|
|
{
|
|
|
|
result = Load(VariableType::JS_POINTER(), gConstAddr,
|
|
|
|
GetGlobalConstantString(ConstantIndex::BIGINT_STRING_INDEX));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotBigInt);
|
|
|
|
{
|
|
|
|
result = Load(VariableType::JS_POINTER(), gConstAddr,
|
|
|
|
GetGlobalConstantString(ConstantIndex::OBJECT_STRING_INDEX));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-03-14 03:50:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&objNotHeapObject);
|
|
|
|
{
|
|
|
|
Label objIsNum(env);
|
|
|
|
Label objNotNum(env);
|
|
|
|
Branch(TaggedIsNumber(obj), &objIsNum, &objNotNum);
|
|
|
|
Bind(&objIsNum);
|
|
|
|
{
|
2022-04-06 06:26:53 +00:00
|
|
|
result = Load(VariableType::JS_POINTER(), gConstAddr,
|
2022-03-14 03:50:02 +00:00
|
|
|
GetGlobalConstantString(ConstantIndex::NUMBER_STRING_INDEX));
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&objNotNum);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
2022-04-06 06:26:53 +00:00
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-03-14 03:50:02 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastStrictEqual(GateRef glue, GateRef left, GateRef right)
|
2022-04-28 01:16:30 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
|
|
|
env->SubCfgEntry(&entry);
|
|
|
|
DEFVARIABLE(result, VariableType::BOOL(), False());
|
|
|
|
Label strictEqual(env);
|
|
|
|
Label leftIsNumber(env);
|
|
|
|
Label leftIsNotNumber(env);
|
|
|
|
Label sameVariableCheck(env);
|
|
|
|
Label stringEqualCheck(env);
|
|
|
|
Label stringCompare(env);
|
|
|
|
Label bigIntEqualCheck(env);
|
|
|
|
Label exit(env);
|
|
|
|
Branch(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
|
|
|
|
Bind(&leftIsNumber);
|
|
|
|
{
|
|
|
|
Label rightIsNumber(env);
|
|
|
|
Branch(TaggedIsNumber(right), &rightIsNumber, &exit);
|
|
|
|
Bind(&rightIsNumber);
|
|
|
|
{
|
|
|
|
DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
|
|
|
|
DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
|
|
|
|
Label leftIsInt(env);
|
|
|
|
Label leftNotInt(env);
|
|
|
|
Label getRight(env);
|
|
|
|
Label numberEqualCheck(env);
|
|
|
|
Branch(TaggedIsInt(left), &leftIsInt, &leftNotInt);
|
|
|
|
Bind(&leftIsInt);
|
|
|
|
{
|
|
|
|
doubleLeft = ChangeInt32ToFloat64(TaggedCastToInt32(left));
|
|
|
|
Jump(&getRight);
|
|
|
|
}
|
|
|
|
Bind(&leftNotInt);
|
|
|
|
{
|
|
|
|
doubleLeft = TaggedCastToDouble(left);
|
|
|
|
Jump(&getRight);
|
|
|
|
}
|
|
|
|
Bind(&getRight);
|
|
|
|
{
|
|
|
|
Label rightIsInt(env);
|
|
|
|
Label rightNotInt(env);
|
|
|
|
Branch(TaggedIsInt(right), &rightIsInt, &rightNotInt);
|
|
|
|
Bind(&rightIsInt);
|
|
|
|
{
|
|
|
|
doubleRight = ChangeInt32ToFloat64(TaggedCastToInt32(right));
|
|
|
|
Jump(&numberEqualCheck);
|
|
|
|
}
|
|
|
|
Bind(&rightNotInt);
|
|
|
|
{
|
|
|
|
doubleRight = TaggedCastToDouble(right);
|
|
|
|
Jump(&numberEqualCheck);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&numberEqualCheck);
|
|
|
|
{
|
|
|
|
Label doubleEqualCheck(env);
|
|
|
|
Branch(BoolOr(DoubleIsNAN(*doubleLeft), DoubleIsNAN(*doubleRight)), &exit, &doubleEqualCheck);
|
|
|
|
Bind(&doubleEqualCheck);
|
|
|
|
{
|
|
|
|
result = DoubleEqual(*doubleLeft, *doubleRight);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftIsNotNumber);
|
|
|
|
Branch(TaggedIsNumber(right), &exit, &sameVariableCheck);
|
|
|
|
Bind(&sameVariableCheck);
|
|
|
|
Branch(Int64Equal(left, right), &strictEqual, &stringEqualCheck);
|
|
|
|
Bind(&stringEqualCheck);
|
2022-08-11 03:18:30 +00:00
|
|
|
Branch(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
|
2022-04-28 01:16:30 +00:00
|
|
|
Bind(&stringCompare);
|
|
|
|
{
|
|
|
|
Label lengthCompare(env);
|
|
|
|
Label hashcodeCompare(env);
|
|
|
|
Label contentsCompare(env);
|
|
|
|
Branch(Int32Equal(ZExtInt1ToInt32(IsUtf16String(left)), ZExtInt1ToInt32(IsUtf16String(right))),
|
|
|
|
&lengthCompare, &exit);
|
|
|
|
Bind(&lengthCompare);
|
|
|
|
Branch(Int32Equal(GetLengthFromString(left), GetLengthFromString(right)), &hashcodeCompare,
|
|
|
|
&exit);
|
|
|
|
Bind(&hashcodeCompare);
|
|
|
|
Branch(Int32Equal(GetHashcodeFromString(glue, left), GetHashcodeFromString(glue, right)), &contentsCompare,
|
|
|
|
&exit);
|
|
|
|
Bind(&contentsCompare);
|
|
|
|
{
|
2022-06-29 01:43:42 +00:00
|
|
|
result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(StringsAreEquals), { left, right });
|
2022-04-28 01:16:30 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&bigIntEqualCheck);
|
|
|
|
{
|
|
|
|
Label leftIsBigInt(env);
|
|
|
|
Label leftIsNotBigInt(env);
|
|
|
|
Branch(TaggedIsBigInt(left), &leftIsBigInt, &exit);
|
|
|
|
Bind(&leftIsBigInt);
|
|
|
|
{
|
|
|
|
Label rightIsBigInt(env);
|
|
|
|
Branch(TaggedIsBigInt(right), &rightIsBigInt, &exit);
|
|
|
|
Bind(&rightIsBigInt);
|
2022-06-29 01:43:42 +00:00
|
|
|
result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
|
2022-04-28 01:16:30 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&strictEqual);
|
|
|
|
{
|
|
|
|
result = True();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastEqual(GateRef left, GateRef right)
|
2022-02-19 02:09:52 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2022-02-19 02:09:52 +00:00
|
|
|
Label leftEqualRight(env);
|
|
|
|
Label leftNotEqualRight(env);
|
|
|
|
Label exit(env);
|
|
|
|
Branch(Int64Equal(left, right), &leftEqualRight, &leftNotEqualRight);
|
|
|
|
Bind(&leftEqualRight);
|
|
|
|
{
|
|
|
|
Label leftIsDouble(env);
|
|
|
|
Label leftNotDoubleOrLeftNotNan(env);
|
|
|
|
Branch(TaggedIsDouble(left), &leftIsDouble, &leftNotDoubleOrLeftNotNan);
|
|
|
|
Bind(&leftIsDouble);
|
|
|
|
{
|
|
|
|
GateRef doubleLeft = TaggedCastToDouble(left);
|
|
|
|
Label leftIsNan(env);
|
|
|
|
Branch(DoubleIsNAN(doubleLeft), &leftIsNan, &leftNotDoubleOrLeftNotNan);
|
|
|
|
Bind(&leftIsNan);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(TaggedFalse());
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftNotDoubleOrLeftNotNan);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(TaggedTrue());
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftNotEqualRight);
|
|
|
|
{
|
|
|
|
Label leftIsNumber(env);
|
|
|
|
Label leftNotNumberOrLeftNotIntOrRightNotInt(env);
|
|
|
|
Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrLeftNotIntOrRightNotInt);
|
|
|
|
Bind(&leftIsNumber);
|
|
|
|
{
|
|
|
|
Label leftIsInt(env);
|
|
|
|
Branch(TaggedIsInt(left), &leftIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
|
|
|
|
Bind(&leftIsInt);
|
|
|
|
{
|
|
|
|
Label rightIsInt(env);
|
|
|
|
Branch(TaggedIsInt(right), &rightIsInt, &leftNotNumberOrLeftNotIntOrRightNotInt);
|
|
|
|
Bind(&rightIsInt);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(TaggedFalse());
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftNotNumberOrLeftNotIntOrRightNotInt);
|
|
|
|
{
|
|
|
|
Label rightIsUndefinedOrNull(env);
|
|
|
|
Label leftOrRightNotUndefinedOrNull(env);
|
|
|
|
Branch(TaggedIsUndefinedOrNull(right), &rightIsUndefinedOrNull, &leftOrRightNotUndefinedOrNull);
|
|
|
|
Bind(&rightIsUndefinedOrNull);
|
|
|
|
{
|
|
|
|
Label leftIsHeapObject(env);
|
|
|
|
Label leftNotHeapObject(env);
|
|
|
|
Branch(TaggedIsHeapObject(left), &leftIsHeapObject, &leftNotHeapObject);
|
|
|
|
Bind(&leftIsHeapObject);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(TaggedFalse());
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&leftNotHeapObject);
|
|
|
|
{
|
|
|
|
Label leftIsUndefinedOrNull(env);
|
|
|
|
Branch(TaggedIsUndefinedOrNull(left), &leftIsUndefinedOrNull, &leftOrRightNotUndefinedOrNull);
|
|
|
|
Bind(&leftIsUndefinedOrNull);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(TaggedTrue());
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftOrRightNotUndefinedOrNull);
|
|
|
|
{
|
|
|
|
Label leftIsBool(env);
|
|
|
|
Label leftNotBoolOrRightNotSpecial(env);
|
|
|
|
Branch(TaggedIsBoolean(left), &leftIsBool, &leftNotBoolOrRightNotSpecial);
|
|
|
|
Bind(&leftIsBool);
|
|
|
|
{
|
|
|
|
Label rightIsSpecial(env);
|
|
|
|
Branch(TaggedIsSpecial(right), &rightIsSpecial, &leftNotBoolOrRightNotSpecial);
|
|
|
|
Bind(&rightIsSpecial);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(TaggedFalse());
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftNotBoolOrRightNotSpecial);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-02-19 02:09:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastToBoolean(GateRef value)
|
2022-04-06 09:02:18 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-04-06 09:02:18 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
|
|
|
Label exit(env);
|
|
|
|
|
|
|
|
Label isSpecial(env);
|
|
|
|
Label notSpecial(env);
|
|
|
|
Label isNumber(env);
|
|
|
|
Label isInt(env);
|
|
|
|
Label isDouble(env);
|
|
|
|
Label notNumber(env);
|
|
|
|
Label notNan(env);
|
|
|
|
Label isString(env);
|
|
|
|
Label notString(env);
|
|
|
|
Label isBigint(env);
|
|
|
|
Label lengthIsOne(env);
|
|
|
|
Label returnTrue(env);
|
|
|
|
Label returnFalse(env);
|
|
|
|
|
|
|
|
Branch(TaggedIsSpecial(value), &isSpecial, ¬Special);
|
|
|
|
Bind(&isSpecial);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsTrue(value), &returnTrue, &returnFalse);
|
|
|
|
}
|
|
|
|
Bind(¬Special);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsNumber(value), &isNumber, ¬Number);
|
|
|
|
Bind(¬Number);
|
|
|
|
{
|
|
|
|
Branch(IsString(value), &isString, ¬String);
|
|
|
|
Bind(&isString);
|
|
|
|
{
|
|
|
|
auto len = GetLengthFromString(value);
|
|
|
|
Branch(Int32Equal(len, Int32(0)), &returnFalse, &returnTrue);
|
|
|
|
}
|
|
|
|
Bind(¬String);
|
2022-07-30 03:49:38 +00:00
|
|
|
Branch(TaggedObjectIsBigInt(value), &isBigint, &returnTrue);
|
2022-04-06 09:02:18 +00:00
|
|
|
Bind(&isBigint);
|
|
|
|
{
|
2022-06-29 01:43:42 +00:00
|
|
|
auto len = Load(VariableType::INT32(), value, IntPtr(BigInt::LENGTH_OFFSET));
|
2022-04-06 09:02:18 +00:00
|
|
|
Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &returnTrue);
|
|
|
|
Bind(&lengthIsOne);
|
|
|
|
{
|
2022-06-29 01:43:42 +00:00
|
|
|
auto data = PtrAdd(value, IntPtr(BigInt::DATA_OFFSET));
|
|
|
|
auto data0 = Load(VariableType::INT32(), data, Int32(0));
|
|
|
|
Branch(Int32Equal(data0, Int32(0)), &returnFalse, &returnTrue);
|
2022-04-06 09:02:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&isNumber);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsInt(value), &isInt, &isDouble);
|
|
|
|
Bind(&isInt);
|
|
|
|
{
|
|
|
|
auto intValue = TaggedCastToInt32(value);
|
|
|
|
Branch(Int32Equal(intValue, Int32(0)), &returnFalse, &returnTrue);
|
|
|
|
}
|
|
|
|
Bind(&isDouble);
|
|
|
|
{
|
|
|
|
auto doubleValue = TaggedCastToDouble(value);
|
|
|
|
Branch(DoubleIsNAN(doubleValue), &returnFalse, ¬Nan);
|
|
|
|
Bind(¬Nan);
|
|
|
|
Branch(DoubleEqual(doubleValue, Double(0.0)), &returnFalse, &returnTrue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&returnTrue);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(TaggedTrue());
|
2022-04-06 09:02:18 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&returnFalse);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = Int64ToTaggedPtr(TaggedFalse());
|
2022-04-06 09:02:18 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-04-06 09:02:18 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastDiv(GateRef left, GateRef right)
|
2022-02-19 02:09:52 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
|
|
|
DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
|
|
|
|
DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
|
2022-02-19 02:09:52 +00:00
|
|
|
Label leftIsNumber(env);
|
|
|
|
Label leftNotNumberOrRightNotNumber(env);
|
|
|
|
Label leftIsNumberAndRightIsNumber(env);
|
|
|
|
Label leftIsDoubleAndRightIsDouble(env);
|
|
|
|
Label exit(env);
|
|
|
|
Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
|
|
|
|
Bind(&leftIsNumber);
|
|
|
|
{
|
|
|
|
Label rightIsNumber(env);
|
|
|
|
Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
|
|
|
|
Bind(&rightIsNumber);
|
|
|
|
{
|
|
|
|
Label leftIsInt(env);
|
|
|
|
Label leftNotInt(env);
|
|
|
|
Branch(TaggedIsInt(left), &leftIsInt, &leftNotInt);
|
|
|
|
Bind(&leftIsInt);
|
|
|
|
{
|
|
|
|
doubleLeft = ChangeInt32ToFloat64(TaggedCastToInt32(left));
|
|
|
|
Jump(&leftIsNumberAndRightIsNumber);
|
|
|
|
}
|
|
|
|
Bind(&leftNotInt);
|
|
|
|
{
|
|
|
|
doubleLeft = TaggedCastToDouble(left);
|
|
|
|
Jump(&leftIsNumberAndRightIsNumber);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftNotNumberOrRightNotNumber);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&leftIsNumberAndRightIsNumber);
|
|
|
|
{
|
|
|
|
Label rightIsInt(env);
|
|
|
|
Label rightNotInt(env);
|
|
|
|
Branch(TaggedIsInt(right), &rightIsInt, &rightNotInt);
|
|
|
|
Bind(&rightIsInt);
|
|
|
|
{
|
|
|
|
doubleRight = ChangeInt32ToFloat64(TaggedCastToInt32(right));
|
|
|
|
Jump(&leftIsDoubleAndRightIsDouble);
|
|
|
|
}
|
|
|
|
Bind(&rightNotInt);
|
|
|
|
{
|
|
|
|
doubleRight = TaggedCastToDouble(right);
|
|
|
|
Jump(&leftIsDoubleAndRightIsDouble);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftIsDoubleAndRightIsDouble);
|
|
|
|
{
|
|
|
|
Label rightIsZero(env);
|
|
|
|
Label rightNotZero(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZero, &rightNotZero);
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&rightIsZero);
|
|
|
|
{
|
|
|
|
Label leftIsZero(env);
|
|
|
|
Label leftNotZero(env);
|
|
|
|
Label leftIsZeroOrNan(env);
|
|
|
|
Label leftNotZeroAndNotNan(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZero, &leftNotZero);
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&leftIsZero);
|
|
|
|
{
|
|
|
|
Jump(&leftIsZeroOrNan);
|
|
|
|
}
|
|
|
|
Bind(&leftNotZero);
|
|
|
|
{
|
|
|
|
Label leftIsNan(env);
|
|
|
|
Branch(DoubleIsNAN(*doubleLeft), &leftIsNan, &leftNotZeroAndNotNan);
|
|
|
|
Bind(&leftIsNan);
|
|
|
|
{
|
|
|
|
Jump(&leftIsZeroOrNan);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftIsZeroOrNan);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&leftNotZeroAndNotNan);
|
|
|
|
{
|
|
|
|
GateRef intLeftTmp = CastDoubleToInt64(*doubleLeft);
|
|
|
|
GateRef intRightTmp = CastDoubleToInt64(*doubleRight);
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef flagBit = Int64And(Int64Xor(intLeftTmp, intRightTmp), Int64(base::DOUBLE_SIGN_MASK));
|
|
|
|
GateRef tmpResult = Int64Xor(flagBit, CastDoubleToInt64(Double(base::POSITIVE_INFINITY)));
|
2022-08-29 07:10:59 +00:00
|
|
|
result = DoubleToTaggedDoublePtr(CastInt64ToFloat64(tmpResult));
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&rightNotZero);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = DoubleToTaggedDoublePtr(DoubleDiv(*doubleLeft, *doubleRight));
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-02-19 02:09:52 +00:00
|
|
|
return ret;
|
2022-03-14 03:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastBinaryOp(GateRef left, GateRef right,
|
2022-07-29 07:26:04 +00:00
|
|
|
const BinaryOperation& intOp,
|
|
|
|
const BinaryOperation& floatOp)
|
2022-03-14 03:50:02 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
|
|
|
DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
|
|
|
|
DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
|
2022-03-14 03:50:02 +00:00
|
|
|
|
|
|
|
Label exit(env);
|
|
|
|
Label doFloatOp(env);
|
2022-03-21 12:06:33 +00:00
|
|
|
Label doIntOp(env);
|
2022-03-14 03:50:02 +00:00
|
|
|
Label leftIsNumber(env);
|
|
|
|
Label rightIsNumber(env);
|
|
|
|
Label leftIsIntRightIsDouble(env);
|
|
|
|
Label rightIsInt(env);
|
|
|
|
Label rightIsDouble(env);
|
|
|
|
|
|
|
|
Branch(TaggedIsNumber(left), &leftIsNumber, &exit);
|
|
|
|
Bind(&leftIsNumber);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsNumber(right), &rightIsNumber, &exit);
|
|
|
|
Bind(&rightIsNumber);
|
|
|
|
{
|
|
|
|
Label leftIsInt(env);
|
|
|
|
Label leftIsDouble(env);
|
|
|
|
Branch(TaggedIsInt(left), &leftIsInt, &leftIsDouble);
|
|
|
|
Bind(&leftIsInt);
|
|
|
|
{
|
2022-03-21 12:06:33 +00:00
|
|
|
Branch(TaggedIsInt(right), &doIntOp, &leftIsIntRightIsDouble);
|
2022-03-14 03:50:02 +00:00
|
|
|
Bind(&leftIsIntRightIsDouble);
|
|
|
|
{
|
|
|
|
doubleLeft = ChangeInt32ToFloat64(TaggedCastToInt32(left));
|
|
|
|
doubleRight = TaggedCastToDouble(right);
|
|
|
|
Jump(&doFloatOp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftIsDouble);
|
|
|
|
{
|
|
|
|
Branch(TaggedIsInt(right), &rightIsInt, &rightIsDouble);
|
|
|
|
Bind(&rightIsInt);
|
|
|
|
{
|
|
|
|
doubleLeft = TaggedCastToDouble(left);
|
|
|
|
doubleRight = ChangeInt32ToFloat64(TaggedCastToInt32(right));
|
|
|
|
Jump(&doFloatOp);
|
|
|
|
}
|
|
|
|
Bind(&rightIsDouble);
|
|
|
|
{
|
|
|
|
doubleLeft = TaggedCastToDouble(left);
|
|
|
|
doubleRight = TaggedCastToDouble(right);
|
|
|
|
Jump(&doFloatOp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-03-21 12:06:33 +00:00
|
|
|
Bind(&doIntOp);
|
|
|
|
{
|
|
|
|
result = intOp(env, left, right);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
2022-03-14 03:50:02 +00:00
|
|
|
Bind(&doFloatOp);
|
|
|
|
{
|
2022-03-21 12:06:33 +00:00
|
|
|
result = floatOp(env, *doubleLeft, *doubleRight);
|
2022-03-14 03:50:02 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-03-14 03:50:02 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-03-21 12:06:33 +00:00
|
|
|
template<OpCode::Op Op>
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastAddSubAndMul(GateRef left, GateRef right)
|
2022-03-21 12:06:33 +00:00
|
|
|
{
|
|
|
|
auto intOperation = [=](Environment *env, GateRef left, GateRef right) {
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2022-03-21 12:06:33 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label overflow(env);
|
|
|
|
Label notOverflow(env);
|
|
|
|
auto res = BinaryOp<Op, MachineType::I64>(TaggedCastToInt64(left), TaggedCastToInt64(right));
|
2022-03-31 09:26:17 +00:00
|
|
|
auto condition1 = Int64GreaterThan(res, Int64(INT32_MAX));
|
|
|
|
auto condition2 = Int64LessThan(res, Int64(INT32_MIN));
|
2022-03-21 12:06:33 +00:00
|
|
|
Branch(BoolOr(condition1, condition2), &overflow, ¬Overflow);
|
|
|
|
Bind(&overflow);
|
|
|
|
{
|
|
|
|
auto doubleLeft = ChangeInt32ToFloat64(TaggedCastToInt32(left));
|
|
|
|
auto doubleRight = ChangeInt32ToFloat64(TaggedCastToInt32(right));
|
2022-03-25 01:31:39 +00:00
|
|
|
auto ret = BinaryOp<Op, MachineType::F64>(doubleLeft, doubleRight);
|
2022-08-29 07:10:59 +00:00
|
|
|
result = DoubleToTaggedDoublePtr(ret);
|
2022-03-21 12:06:33 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Overflow);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = IntToTaggedPtr(ChangeInt64ToInt32(res));
|
2022-03-21 12:06:33 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-03-21 12:06:33 +00:00
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
auto floatOperation = [=]([[maybe_unused]] Environment *env, GateRef left, GateRef right) {
|
|
|
|
auto res = BinaryOp<Op, MachineType::F64>(left, right);
|
2022-08-29 07:10:59 +00:00
|
|
|
return DoubleToTaggedDoublePtr(res);
|
2022-03-21 12:06:33 +00:00
|
|
|
};
|
|
|
|
return FastBinaryOp(left, right, intOperation, floatOperation);
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastAdd(GateRef left, GateRef right)
|
2022-03-14 03:50:02 +00:00
|
|
|
{
|
2022-03-21 12:06:33 +00:00
|
|
|
return FastAddSubAndMul<OpCode::ADD>(left, right);
|
2022-03-14 03:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastSub(GateRef left, GateRef right)
|
2022-03-14 03:50:02 +00:00
|
|
|
{
|
2022-03-21 12:06:33 +00:00
|
|
|
return FastAddSubAndMul<OpCode::SUB>(left, right);
|
2022-03-14 03:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastMul(GateRef left, GateRef right)
|
2022-03-14 03:50:02 +00:00
|
|
|
{
|
2022-03-21 12:06:33 +00:00
|
|
|
return FastAddSubAndMul<OpCode::MUL>(left, right);
|
2022-02-19 02:09:52 +00:00
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::FastMod(GateRef glue, GateRef left, GateRef right)
|
2022-02-19 02:09:52 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
|
|
|
DEFVARIABLE(intLeft, VariableType::INT32(), Int32(0));
|
|
|
|
DEFVARIABLE(intRight, VariableType::INT32(), Int32(0));
|
|
|
|
DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0));
|
|
|
|
DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0));
|
2022-02-19 02:09:52 +00:00
|
|
|
Label leftIsInt(env);
|
|
|
|
Label leftNotIntOrRightNotInt(env);
|
|
|
|
Label exit(env);
|
|
|
|
Branch(TaggedIsInt(left), &leftIsInt, &leftNotIntOrRightNotInt);
|
|
|
|
Bind(&leftIsInt);
|
|
|
|
{
|
|
|
|
Label rightIsInt(env);
|
|
|
|
Branch(TaggedIsInt(right), &rightIsInt, &leftNotIntOrRightNotInt);
|
|
|
|
Bind(&rightIsInt);
|
|
|
|
{
|
|
|
|
intLeft = TaggedCastToInt32(left);
|
|
|
|
intRight = TaggedCastToInt32(right);
|
|
|
|
Label leftGreaterZero(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32GreaterThan(*intLeft, Int32(0)), &leftGreaterZero, &leftNotIntOrRightNotInt);
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&leftGreaterZero);
|
|
|
|
{
|
|
|
|
Label rightGreaterZero(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32GreaterThan(*intRight, Int32(0)), &rightGreaterZero, &leftNotIntOrRightNotInt);
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&rightGreaterZero);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = IntToTaggedPtr(Int32Mod(*intLeft, *intRight));
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftNotIntOrRightNotInt);
|
|
|
|
{
|
|
|
|
Label leftIsNumber(env);
|
|
|
|
Label leftNotNumberOrRightNotNumber(env);
|
|
|
|
Label leftIsNumberAndRightIsNumber(env);
|
|
|
|
Label leftIsDoubleAndRightIsDouble(env);
|
|
|
|
Branch(TaggedIsNumber(left), &leftIsNumber, &leftNotNumberOrRightNotNumber);
|
|
|
|
Bind(&leftIsNumber);
|
|
|
|
{
|
|
|
|
Label rightIsNumber(env);
|
|
|
|
Branch(TaggedIsNumber(right), &rightIsNumber, &leftNotNumberOrRightNotNumber);
|
|
|
|
Bind(&rightIsNumber);
|
|
|
|
{
|
|
|
|
Label leftIsInt1(env);
|
|
|
|
Label leftNotInt1(env);
|
|
|
|
Branch(TaggedIsInt(left), &leftIsInt1, &leftNotInt1);
|
|
|
|
Bind(&leftIsInt1);
|
|
|
|
{
|
|
|
|
doubleLeft = ChangeInt32ToFloat64(TaggedCastToInt32(left));
|
|
|
|
Jump(&leftIsNumberAndRightIsNumber);
|
|
|
|
}
|
|
|
|
Bind(&leftNotInt1);
|
|
|
|
{
|
|
|
|
doubleLeft = TaggedCastToDouble(left);
|
|
|
|
Jump(&leftIsNumberAndRightIsNumber);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftNotNumberOrRightNotNumber);
|
|
|
|
{
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&leftIsNumberAndRightIsNumber);
|
|
|
|
{
|
|
|
|
Label rightIsInt1(env);
|
|
|
|
Label rightNotInt1(env);
|
|
|
|
Branch(TaggedIsInt(right), &rightIsInt1, &rightNotInt1);
|
|
|
|
Bind(&rightIsInt1);
|
|
|
|
{
|
|
|
|
doubleRight = ChangeInt32ToFloat64(TaggedCastToInt32(right));
|
|
|
|
Jump(&leftIsDoubleAndRightIsDouble);
|
|
|
|
}
|
|
|
|
Bind(&rightNotInt1);
|
|
|
|
{
|
|
|
|
doubleRight = TaggedCastToDouble(right);
|
|
|
|
Jump(&leftIsDoubleAndRightIsDouble);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftIsDoubleAndRightIsDouble);
|
|
|
|
{
|
|
|
|
Label rightNotZero(env);
|
|
|
|
Label rightIsZeroOrNanOrLeftIsNanOrInf(env);
|
|
|
|
Label rightNotZeroAndNanAndLeftNotNanAndInf(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(DoubleEqual(*doubleRight, Double(0.0)), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotZero);
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&rightNotZero);
|
|
|
|
{
|
|
|
|
Label rightNotNan(env);
|
|
|
|
Branch(DoubleIsNAN(*doubleRight), &rightIsZeroOrNanOrLeftIsNanOrInf, &rightNotNan);
|
|
|
|
Bind(&rightNotNan);
|
|
|
|
{
|
|
|
|
Label leftNotNan(env);
|
|
|
|
Branch(DoubleIsNAN(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf, &leftNotNan);
|
|
|
|
Bind(&leftNotNan);
|
|
|
|
{
|
|
|
|
Branch(DoubleIsINF(*doubleLeft), &rightIsZeroOrNanOrLeftIsNanOrInf,
|
|
|
|
&rightNotZeroAndNanAndLeftNotNanAndInf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&rightIsZeroOrNanOrLeftIsNanOrInf);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = DoubleToTaggedDoublePtr(Double(base::NAN_VALUE));
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&rightNotZeroAndNanAndLeftNotNanAndInf);
|
|
|
|
{
|
|
|
|
Label leftNotZero(env);
|
|
|
|
Label leftIsZeroOrRightIsInf(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(DoubleEqual(*doubleLeft, Double(0.0)), &leftIsZeroOrRightIsInf, &leftNotZero);
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(&leftNotZero);
|
|
|
|
{
|
|
|
|
Label rightNotInf(env);
|
|
|
|
Branch(DoubleIsINF(*doubleRight), &leftIsZeroOrRightIsInf, &rightNotInf);
|
|
|
|
Bind(&rightNotInf);
|
|
|
|
{
|
2022-06-29 01:43:42 +00:00
|
|
|
result = UpdateLeaveFrameAndCallNGCRuntime(
|
|
|
|
glue, RTSTUB_ID(FloatMod), { *doubleLeft, *doubleRight });
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&leftIsZeroOrRightIsInf);
|
|
|
|
{
|
2022-08-29 07:10:59 +00:00
|
|
|
result = DoubleToTaggedDoublePtr(*doubleLeft);
|
2022-02-19 02:09:52 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-02-19 02:09:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetGlobalOwnProperty(GateRef glue, GateRef receiver, GateRef key)
|
2022-02-19 02:09:52 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entryLabel(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entryLabel);
|
2022-03-31 09:26:17 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2022-02-19 02:09:52 +00:00
|
|
|
GateRef properties = GetPropertiesFromJSObject(receiver);
|
|
|
|
GateRef entry = FindEntryFromNameDictionary(glue, properties, key);
|
|
|
|
Label notNegtiveOne(env);
|
|
|
|
Label exit(env);
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32NotEqual(entry, Int32(-1)), ¬NegtiveOne, &exit);
|
2022-02-19 02:09:52 +00:00
|
|
|
Bind(¬NegtiveOne);
|
|
|
|
{
|
|
|
|
result = GetValueFromGlobalDictionary(properties, entry);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-02-19 02:09:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index)
|
2022-01-04 11:30:40 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-01-04 11:30:40 +00:00
|
|
|
Label exit(env);
|
2022-06-16 03:01:51 +00:00
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
2022-01-04 11:30:40 +00:00
|
|
|
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef lengthOffset = IntPtr(panda::ecmascript::JSAPIArrayList::LENGTH_OFFSET);
|
2022-03-01 08:31:08 +00:00
|
|
|
GateRef length = TaggedCastToInt32(Load(VariableType::INT64(), receiver, lengthOffset));
|
2022-01-04 11:30:40 +00:00
|
|
|
Label isVailedIndex(env);
|
|
|
|
Label notValidIndex(env);
|
2022-08-11 03:18:30 +00:00
|
|
|
Branch(BoolAnd(Int32GreaterThanOrEqual(index, Int32(0)),
|
|
|
|
Int32UnsignedLessThan(index, length)), &isVailedIndex, ¬ValidIndex);
|
2022-01-04 11:30:40 +00:00
|
|
|
Bind(&isVailedIndex);
|
|
|
|
{
|
|
|
|
GateRef elements = GetElementsArray(receiver);
|
2022-03-01 08:31:08 +00:00
|
|
|
result = GetValueFromTaggedArray(VariableType::JS_ANY(), elements, index);
|
2022-01-04 11:30:40 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬ValidIndex);
|
|
|
|
{
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(GetPropertyOutOfBounds));
|
2022-08-29 07:10:59 +00:00
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
|
2022-03-31 09:26:17 +00:00
|
|
|
result = Exception();
|
2022-01-04 11:30:40 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-01-04 11:30:40 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2022-03-07 06:42:40 +00:00
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::DoubleToInt(GateRef glue, GateRef x)
|
2022-03-07 06:42:40 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-03-07 06:42:40 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label overflow(env);
|
|
|
|
|
|
|
|
GateRef xInt = ChangeFloat64ToInt32(x);
|
|
|
|
DEFVARIABLE(result, VariableType::INT32(), xInt);
|
|
|
|
|
|
|
|
if (env->IsAmd64()) {
|
|
|
|
// 0x80000000: amd64 overflow return value
|
2022-03-31 09:26:17 +00:00
|
|
|
Branch(Int32Equal(xInt, Int32(0x80000000)), &overflow, &exit);
|
2022-03-07 06:42:40 +00:00
|
|
|
} else {
|
|
|
|
GateRef xInt64 = CastDoubleToInt64(x);
|
|
|
|
// exp = (u64 & DOUBLE_EXPONENT_MASK) >> DOUBLE_SIGNIFICAND_SIZE - DOUBLE_EXPONENT_BIAS
|
2022-03-31 09:26:17 +00:00
|
|
|
GateRef exp = Int64And(xInt64, Int64(base::DOUBLE_EXPONENT_MASK));
|
2022-04-21 12:08:23 +00:00
|
|
|
exp = ChangeInt64ToInt32(Int64LSR(exp, Int64(base::DOUBLE_SIGNIFICAND_SIZE)));
|
2022-03-31 09:26:17 +00:00
|
|
|
exp = Int32Sub(exp, Int32(base::DOUBLE_EXPONENT_BIAS));
|
|
|
|
GateRef bits = Int32(base::INT32_BITS - 1);
|
2022-03-07 06:42:40 +00:00
|
|
|
// exp < 32 - 1
|
|
|
|
Branch(Int32LessThan(exp, bits), &exit, &overflow);
|
|
|
|
}
|
|
|
|
Bind(&overflow);
|
|
|
|
{
|
2022-06-29 01:43:42 +00:00
|
|
|
result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(DoubleToInt), { x });
|
2022-03-07 06:42:40 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-03-07 06:42:40 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2022-04-08 05:26:13 +00:00
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
void StubBuilder::ReturnExceptionIfAbruptCompletion(GateRef glue)
|
2022-04-08 05:26:13 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgEntry(&entry);
|
2022-04-08 05:26:13 +00:00
|
|
|
Label exit(env);
|
|
|
|
Label hasPendingException(env);
|
2022-06-29 02:17:21 +00:00
|
|
|
GateRef exceptionOffset = IntPtr(JSThread::GlueData::GetExceptionOffset(env->IsArch32Bit()));
|
|
|
|
GateRef exception = Load(VariableType::JS_ANY(), glue, exceptionOffset);
|
2022-04-08 05:26:13 +00:00
|
|
|
Branch(Int64NotEqual(exception, Int64(JSTaggedValue::VALUE_HOLE)), &hasPendingException, &exit);
|
|
|
|
Bind(&hasPendingException);
|
|
|
|
Return(Exception());
|
|
|
|
Bind(&exit);
|
2022-04-15 03:30:10 +00:00
|
|
|
env->SubCfgExit();
|
2022-04-08 05:26:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-04-28 01:16:30 +00:00
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
|
2022-04-28 01:16:30 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label subentry(env);
|
|
|
|
env->SubCfgEntry(&subentry);
|
|
|
|
Label noRawHashcode(env);
|
|
|
|
Label exit(env);
|
|
|
|
DEFVARIABLE(hashcode, VariableType::INT32(), Int32(0));
|
|
|
|
hashcode = Load(VariableType::INT32(), value, IntPtr(EcmaString::HASHCODE_OFFSET));
|
|
|
|
Branch(Int32Equal(*hashcode, Int32(0)), &noRawHashcode, &exit);
|
|
|
|
Bind(&noRawHashcode);
|
|
|
|
{
|
|
|
|
hashcode = TaggedCastToInt32(CallRuntime(glue, RTSTUB_ID(ComputeHashcode), { value }));
|
|
|
|
Store(VariableType::INT32(), glue, value, IntPtr(EcmaString::HASHCODE_OFFSET), *hashcode);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *hashcode;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-05-19 04:48:40 +00:00
|
|
|
|
2022-06-30 02:22:52 +00:00
|
|
|
GateRef StubBuilder::ConstructorCheck(GateRef glue, GateRef ctor, GateRef outPut, GateRef thisObj)
|
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entryPass(env);
|
|
|
|
Label exit(env);
|
|
|
|
env->SubCfgEntry(&entryPass);
|
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
|
|
|
|
Label isHeapObject(env);
|
|
|
|
Label isEcmaObj(env);
|
|
|
|
Label notEcmaObj(env);
|
|
|
|
Branch(TaggedIsHeapObject(outPut), &isHeapObject, ¬EcmaObj);
|
|
|
|
Bind(&isHeapObject);
|
|
|
|
Branch(TaggedObjectIsEcmaObject(outPut), &isEcmaObj, ¬EcmaObj);
|
|
|
|
Bind(&isEcmaObj);
|
|
|
|
{
|
|
|
|
result = outPut;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬EcmaObj);
|
|
|
|
{
|
|
|
|
Label ctorIsBase(env);
|
|
|
|
Label ctorNotBase(env);
|
|
|
|
Branch(IsBase(ctor), &ctorIsBase, &ctorNotBase);
|
|
|
|
Bind(&ctorIsBase);
|
|
|
|
{
|
|
|
|
result = thisObj;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&ctorNotBase);
|
|
|
|
{
|
|
|
|
Label throwExeption(env);
|
|
|
|
Label returnObj(env);
|
|
|
|
Branch(TaggedIsUndefined(outPut), &returnObj, &throwExeption);
|
|
|
|
Bind(&returnObj);
|
|
|
|
result = thisObj;
|
|
|
|
Jump(&exit);
|
|
|
|
Bind(&throwExeption);
|
|
|
|
{
|
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowNonConstructorException), {});
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::JSCallDispatch(GateRef glue, GateRef func, GateRef actualNumArgs,
|
2022-06-30 02:22:52 +00:00
|
|
|
JSCallMode mode, std::initializer_list<GateRef> args)
|
2022-05-30 02:41:07 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entryPass(env);
|
|
|
|
Label exit(env);
|
|
|
|
env->SubCfgEntry(&entryPass);
|
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Exception());
|
|
|
|
// 1. call initialize
|
|
|
|
Label funcIsHeapObject(env);
|
|
|
|
Label funcIsCallable(env);
|
|
|
|
Label funcNotCallable(env);
|
2022-08-04 06:58:57 +00:00
|
|
|
Label isFastBuiltins(env);
|
|
|
|
Label notFastBuiltins(env);
|
2022-05-30 02:41:07 +00:00
|
|
|
// save pc
|
|
|
|
SavePcIfNeeded(glue);
|
2022-06-08 03:57:26 +00:00
|
|
|
GateRef bitfield = 0;
|
|
|
|
if (mode != JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV) {
|
|
|
|
Branch(TaggedIsHeapObject(func), &funcIsHeapObject, &funcNotCallable);
|
|
|
|
Bind(&funcIsHeapObject);
|
|
|
|
GateRef hclass = LoadHClass(func);
|
|
|
|
bitfield = Load(VariableType::INT32(), hclass, IntPtr(JSHClass::BIT_FIELD_OFFSET));
|
|
|
|
Branch(IsCallableFromBitField(bitfield), &funcIsCallable, &funcNotCallable);
|
|
|
|
Bind(&funcNotCallable);
|
|
|
|
{
|
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowNotCallableException), {});
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&funcIsCallable);
|
2022-05-30 02:41:07 +00:00
|
|
|
}
|
|
|
|
GateRef method = GetMethodFromJSFunction(func);
|
|
|
|
GateRef callField = GetCallFieldFromMethod(method);
|
2022-08-16 13:05:02 +00:00
|
|
|
GateRef isNativeMask = Int64(static_cast<uint64_t>(1) << MethodLiteral::IsNativeBit::START_BIT);
|
2022-05-30 02:41:07 +00:00
|
|
|
|
|
|
|
// 2. call dispatch
|
|
|
|
Label methodIsNative(env);
|
|
|
|
Label methodNotNative(env);
|
|
|
|
Branch(Int64NotEqual(Int64And(callField, isNativeMask), Int64(0)), &methodIsNative, &methodNotNative);
|
|
|
|
auto data = std::begin(args);
|
|
|
|
// 3. call native
|
|
|
|
Bind(&methodIsNative);
|
|
|
|
{
|
|
|
|
GateRef nativeCode = Load(VariableType::NATIVE_POINTER(), method,
|
2022-08-23 01:56:32 +00:00
|
|
|
IntPtr(Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
|
2022-05-30 02:41:07 +00:00
|
|
|
GateRef newTarget = Undefined();
|
|
|
|
GateRef thisValue = Undefined();
|
2022-07-15 09:21:11 +00:00
|
|
|
GateRef numArgs = Int32Add(actualNumArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS));
|
2022-05-30 02:41:07 +00:00
|
|
|
switch (mode) {
|
|
|
|
case JSCallMode::CALL_ARG0:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
|
2022-07-15 09:21:11 +00:00
|
|
|
{ nativeCode, glue, numArgs, func, newTarget, thisValue });
|
2022-05-30 02:41:07 +00:00
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG1:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
|
2022-07-15 09:21:11 +00:00
|
|
|
{ nativeCode, glue, numArgs, func, newTarget, thisValue, data[0]});
|
2022-05-30 02:41:07 +00:00
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG2:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
|
2022-07-15 09:21:11 +00:00
|
|
|
{ nativeCode, glue, numArgs, func, newTarget, thisValue, data[0], data[1] });
|
2022-05-30 02:41:07 +00:00
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG3:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
|
2022-07-15 09:21:11 +00:00
|
|
|
{ nativeCode, glue, numArgs, func,
|
2022-05-30 02:41:07 +00:00
|
|
|
newTarget, thisValue, data[0], data[1], data[2] }); // 2: args2
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_THIS_WITH_ARGV: {
|
|
|
|
thisValue = data[2]; // 2: this input
|
2022-08-16 13:05:02 +00:00
|
|
|
GateRef isFastBuiltinsMask =
|
|
|
|
Int64(static_cast<uint64_t>(1) << MethodLiteral::IsFastBuiltinBit::START_BIT);
|
2022-08-04 06:58:57 +00:00
|
|
|
Branch(Int64NotEqual(Int64And(callField, isFastBuiltinsMask), Int64(0)),
|
|
|
|
&isFastBuiltins, ¬FastBuiltins);
|
|
|
|
Bind(&isFastBuiltins);
|
|
|
|
{
|
|
|
|
GateRef builtinId = GetBuiltinId(method);
|
|
|
|
result = DispatchBuiltins(glue, builtinId, { glue, nativeCode, func, thisValue, data[0], data[1] });
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬FastBuiltins);
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallIRangeAndDispatchNative),
|
|
|
|
{ glue, nativeCode, func, thisValue, data[0], data[1] });
|
|
|
|
break;
|
2022-05-30 02:41:07 +00:00
|
|
|
}
|
|
|
|
case JSCallMode::CALL_WITH_ARGV:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallIRangeAndDispatchNative),
|
|
|
|
{ glue, nativeCode, func, thisValue, data[0], data[1] });
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
|
2022-06-08 03:57:26 +00:00
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallNewAndDispatchNative),
|
|
|
|
{ glue, nativeCode, func, data[2], data[0], data[1] });
|
2022-05-30 02:41:07 +00:00
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_GETTER:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
|
2022-07-15 09:21:11 +00:00
|
|
|
{ nativeCode, glue, numArgs, func, newTarget, data[0] });
|
2022-05-30 02:41:07 +00:00
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_SETTER:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgsAndDispatchNative),
|
2022-07-15 09:21:11 +00:00
|
|
|
{ nativeCode, glue, numArgs, func, newTarget, data[0], data[1] });
|
2022-05-30 02:41:07 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
// 4. call nonNative
|
|
|
|
Bind(&methodNotNative);
|
2022-06-18 07:09:19 +00:00
|
|
|
Label funcIsClassConstructor(env);
|
|
|
|
Label funcNotClassConstructor(env);
|
2022-06-08 03:57:26 +00:00
|
|
|
if (mode != JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV) {
|
|
|
|
Branch(IsClassConstructorFromBitField(bitfield), &funcIsClassConstructor, &funcNotClassConstructor);
|
|
|
|
Bind(&funcIsClassConstructor);
|
|
|
|
{
|
|
|
|
CallRuntime(glue, RTSTUB_ID(ThrowCallConstructorException), {});
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(&funcNotClassConstructor);
|
2022-05-30 02:41:07 +00:00
|
|
|
}
|
|
|
|
GateRef sp = 0;
|
|
|
|
if (env->IsAsmInterp()) {
|
2022-07-21 01:51:36 +00:00
|
|
|
sp = Argument(static_cast<size_t>(InterpreterHandlerInputs::SP));
|
2022-05-30 02:41:07 +00:00
|
|
|
}
|
2022-06-18 07:09:19 +00:00
|
|
|
Label methodisAot(env);
|
|
|
|
Label methodNotAot(env);
|
2022-05-30 02:41:07 +00:00
|
|
|
{
|
2022-08-16 13:05:02 +00:00
|
|
|
GateRef isAotMask = Int64(static_cast<uint64_t>(1) << MethodLiteral::IsAotCodeBit::START_BIT);
|
2022-06-20 12:58:32 +00:00
|
|
|
Branch(Int64Equal(Int64And(callField, isAotMask), Int64(0)), &methodNotAot, &methodisAot);
|
|
|
|
Bind(&methodisAot);
|
|
|
|
{
|
|
|
|
GateRef newTarget = Undefined();
|
|
|
|
GateRef thisValue = Undefined();
|
2022-07-25 01:53:14 +00:00
|
|
|
GateRef lexEnv = env_->GetBuilder()->GetLexicalEnv(func);
|
2022-07-06 01:53:50 +00:00
|
|
|
GateRef realNumArgs = Int64Add(ZExtInt32ToInt64(actualNumArgs), Int64(NUM_MANDATORY_JSFUNC_ARGS));
|
2022-06-20 12:58:32 +00:00
|
|
|
switch (mode) {
|
|
|
|
case JSCallMode::CALL_ARG0:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
|
2022-06-29 09:09:09 +00:00
|
|
|
{ glue, lexEnv, realNumArgs, func, newTarget, thisValue});
|
2022-06-20 12:58:32 +00:00
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG1:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
|
2022-06-29 09:09:09 +00:00
|
|
|
{ glue, lexEnv, realNumArgs, func, newTarget, thisValue, data[0] });
|
2022-06-20 12:58:32 +00:00
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG2:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
|
2022-06-29 09:09:09 +00:00
|
|
|
{ glue, lexEnv, realNumArgs, func, newTarget, thisValue, data[0], data[1] });
|
2022-06-20 12:58:32 +00:00
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG3:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
|
2022-06-29 09:09:09 +00:00
|
|
|
{ glue, lexEnv, realNumArgs, func, newTarget, thisValue,
|
2022-06-20 12:58:32 +00:00
|
|
|
data[0], data[1], data[2] }); // 2: args2
|
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_THIS_WITH_ARGV:
|
|
|
|
thisValue = data[2]; // 2: this input
|
|
|
|
[[fallthrough]];
|
|
|
|
case JSCallMode::CALL_WITH_ARGV:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(JSCallWithArgV),
|
2022-07-06 01:53:50 +00:00
|
|
|
{ glue, ZExtInt32ToInt64(actualNumArgs), func, newTarget, thisValue, data[1] });
|
2022-06-20 12:58:32 +00:00
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
|
2022-07-22 09:12:45 +00:00
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(ConstructorJSCallWithArgV),
|
2022-07-06 01:53:50 +00:00
|
|
|
{ glue, ZExtInt32ToInt64(actualNumArgs), func, func, data[2], data[1]});
|
2022-07-29 07:27:17 +00:00
|
|
|
result = ConstructorCheck(glue, func, *result, data[2]); // 2: the second index
|
2022-06-20 12:58:32 +00:00
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_GETTER:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
|
2022-06-29 09:09:09 +00:00
|
|
|
{ glue, lexEnv, realNumArgs, func, newTarget, data[0]});
|
2022-06-20 12:58:32 +00:00
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_SETTER:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
|
2022-06-29 09:09:09 +00:00
|
|
|
{ glue, lexEnv, realNumArgs, func, newTarget, data[0], data[1]});
|
2022-06-20 12:58:32 +00:00
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
2022-06-17 10:26:05 +00:00
|
|
|
}
|
|
|
|
}
|
2022-06-20 12:58:32 +00:00
|
|
|
Bind(&methodNotAot);
|
2022-05-30 02:41:07 +00:00
|
|
|
switch (mode) {
|
|
|
|
case JSCallMode::CALL_ARG0:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs0AndDispatch),
|
|
|
|
{ glue, sp, func, method, callField });
|
|
|
|
Return();
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG1:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs1AndDispatch),
|
|
|
|
{ glue, sp, func, method, callField, data[0] });
|
|
|
|
Return();
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG2:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs2AndDispatch),
|
|
|
|
{ glue, sp, func, method, callField, data[0], data[1] });
|
|
|
|
Return();
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_ARG3:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallArgs3AndDispatch),
|
|
|
|
{ glue, sp, func, method, callField, data[0], data[1], data[2] }); // 2: args2
|
|
|
|
Return();
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_WITH_ARGV:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallIRangeAndDispatch),
|
|
|
|
{ glue, sp, func, method, callField, data[0], data[1] });
|
|
|
|
Return();
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_THIS_WITH_ARGV:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallIThisRangeAndDispatch),
|
2022-06-08 01:22:37 +00:00
|
|
|
{ glue, sp, func, method, callField, data[0], data[1], data[2] });
|
2022-05-30 02:41:07 +00:00
|
|
|
Return();
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_CONSTRUCTOR_WITH_ARGV:
|
2022-06-08 03:57:26 +00:00
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(PushCallNewAndDispatch),
|
|
|
|
{ glue, sp, func, method, callField, data[0], data[1], data[2] });
|
|
|
|
Return();
|
2022-05-30 02:41:07 +00:00
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_GETTER:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(CallGetter),
|
|
|
|
{ glue, func, method, callField, data[0] });
|
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
case JSCallMode::CALL_SETTER:
|
|
|
|
result = CallNGCRuntime(glue, RTSTUB_ID(CallSetter),
|
2022-06-08 03:57:26 +00:00
|
|
|
{ glue, func, method, callField, data[1], data[0] });
|
2022-05-30 02:41:07 +00:00
|
|
|
Jump(&exit);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
2022-06-10 07:33:31 +00:00
|
|
|
|
2022-07-22 02:27:59 +00:00
|
|
|
GateRef StubBuilder::TryStringOrSymbelToElementIndex(GateRef key)
|
2022-06-10 07:33:31 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
|
|
|
env->SubCfgEntry(&entry);
|
|
|
|
Label exit(env);
|
|
|
|
DEFVARIABLE(result, VariableType::INT32(), Int32(-1));
|
|
|
|
|
|
|
|
Label keyNotSymbol(env);
|
|
|
|
Branch(IsSymbol(key), &exit, &keyNotSymbol);
|
|
|
|
Bind(&keyNotSymbol);
|
|
|
|
|
|
|
|
Label greatThanZero(env);
|
|
|
|
Label inRange(env);
|
|
|
|
auto len = GetLengthFromString(key);
|
|
|
|
Branch(Int32Equal(len, Int32(0)), &exit, &greatThanZero);
|
|
|
|
Bind(&greatThanZero);
|
|
|
|
Branch(Int32GreaterThan(len, Int32(MAX_INDEX_LEN)), &exit, &inRange);
|
|
|
|
Bind(&inRange);
|
|
|
|
{
|
|
|
|
Label isUtf8(env);
|
|
|
|
Branch(IsUtf16String(key), &exit, &isUtf8);
|
|
|
|
Bind(&isUtf8);
|
|
|
|
|
|
|
|
GateRef data = PtrAdd(key, IntPtr(EcmaString::DATA_OFFSET));
|
|
|
|
DEFVARIABLE(c, VariableType::INT32(), Int32(0));
|
|
|
|
c = ZExtInt8ToInt32(Load(VariableType::INT8(), data));
|
|
|
|
Label isDigitZero(env);
|
|
|
|
Label notDigitZero(env);
|
|
|
|
Branch(Int32Equal(*c, Int32('0')), &isDigitZero, ¬DigitZero);
|
|
|
|
Bind(&isDigitZero);
|
|
|
|
{
|
|
|
|
Label lengthIsOne(env);
|
|
|
|
Branch(Int32Equal(len, Int32(1)), &lengthIsOne, &exit);
|
|
|
|
Bind(&lengthIsOne);
|
|
|
|
{
|
|
|
|
result = Int32(0);
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬DigitZero);
|
|
|
|
{
|
|
|
|
Label isDigit(env);
|
|
|
|
Label notIsDigit(env);
|
|
|
|
DEFVARIABLE(i, VariableType::INT32(), Int32(1));
|
|
|
|
DEFVARIABLE(n, VariableType::INT32(), Int32Sub(*c, Int32('0')));
|
|
|
|
|
|
|
|
Branch(IsDigit(*c), &isDigit, ¬IsDigit);
|
|
|
|
Label loopHead(env);
|
|
|
|
Label loopEnd(env);
|
|
|
|
Label afterLoop(env);
|
|
|
|
Bind(&isDigit);
|
|
|
|
Branch(Int32UnsignedLessThan(*i, len), &loopHead, &afterLoop);
|
|
|
|
LoopBegin(&loopHead);
|
|
|
|
{
|
|
|
|
c = ZExtInt8ToInt32(Load(VariableType::INT8(), data, ChangeInt32ToIntPtr(*i)));
|
|
|
|
Label isDigit2(env);
|
|
|
|
Label notDigit2(env);
|
|
|
|
Branch(IsDigit(*c), &isDigit2, ¬Digit2);
|
|
|
|
Bind(&isDigit2);
|
|
|
|
{
|
|
|
|
// 10 means the base of digit is 10.
|
|
|
|
n = Int32Add(Int32Mul(*n, Int32(10)),
|
|
|
|
Int32Sub(*c, Int32('0')));
|
|
|
|
i = Int32Add(*i, Int32(1));
|
|
|
|
Branch(Int32UnsignedLessThan(*i, len), &loopEnd, &afterLoop);
|
|
|
|
}
|
|
|
|
Bind(¬Digit2);
|
|
|
|
{
|
|
|
|
Label hasPoint(env);
|
|
|
|
Branch(Int32Equal(*c, Int32('.')), &hasPoint, &exit);
|
|
|
|
Bind(&hasPoint);
|
|
|
|
{
|
|
|
|
result = Int32(-2); // -2:return -2 means should goto slow path
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&loopEnd);
|
|
|
|
LoopEnd(&loopHead);
|
|
|
|
Bind(&afterLoop);
|
|
|
|
{
|
|
|
|
Label lessThanMaxIndex(env);
|
|
|
|
Branch(Int32UnsignedLessThan(*n, Int32(JSObject::MAX_ELEMENT_INDEX)),
|
|
|
|
&lessThanMaxIndex, &exit);
|
|
|
|
Bind(&lessThanMaxIndex);
|
|
|
|
{
|
|
|
|
result = *n;
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(¬IsDigit);
|
|
|
|
{
|
|
|
|
Label isNegative(env);
|
|
|
|
Branch(Int32Equal(*c, Int32('-')), &isNegative, &exit);
|
|
|
|
Bind(&isNegative);
|
|
|
|
{
|
|
|
|
result = Int32(-2); // -2:return -2 means should goto slow path
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-29 07:27:17 +00:00
|
|
|
GateRef StubBuilder::GetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder,
|
|
|
|
GateRef key, GateRef jsType)
|
2022-06-10 07:33:31 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
|
|
|
env->SubCfgEntry(&entry);
|
|
|
|
Label exit(env);
|
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
|
|
|
|
|
|
|
Label notOnProtoChain(env);
|
|
|
|
Branch(Int64NotEqual(receiver, holder), &exit, ¬OnProtoChain);
|
|
|
|
Bind(¬OnProtoChain);
|
|
|
|
|
|
|
|
auto negativeZero = GetGlobalConstantValue(
|
|
|
|
VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
|
|
|
|
Label isNegativeZero(env);
|
|
|
|
Label notNegativeZero(env);
|
|
|
|
Branch(Int64Equal(negativeZero, key), &isNegativeZero, ¬NegativeZero);
|
|
|
|
Bind(&isNegativeZero);
|
|
|
|
{
|
|
|
|
result = Undefined();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬NegativeZero);
|
|
|
|
{
|
|
|
|
GateRef index = TryStringOrSymbelToElementIndex(key);
|
|
|
|
Label validIndex(env);
|
|
|
|
Label notValidIndex(env);
|
|
|
|
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
|
|
|
|
Bind(&validIndex);
|
|
|
|
{
|
|
|
|
result = CallRuntime(glue, RTSTUB_ID(GetTypeArrayPropertyByIndex),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ holder, IntToTaggedInt(index), IntToTaggedInt(jsType) });
|
2022-06-10 07:33:31 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬ValidIndex);
|
|
|
|
{
|
|
|
|
Label returnNull(env);
|
|
|
|
Branch(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
|
|
|
|
Bind(&returnNull);
|
|
|
|
{
|
|
|
|
result = Null();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2022-07-29 07:27:17 +00:00
|
|
|
GateRef StubBuilder::SetTypeArrayPropertyByName(GateRef glue, GateRef receiver, GateRef holder, GateRef key,
|
|
|
|
GateRef value, GateRef jsType)
|
2022-06-10 07:33:31 +00:00
|
|
|
{
|
|
|
|
auto env = GetEnvironment();
|
|
|
|
Label entry(env);
|
|
|
|
env->SubCfgEntry(&entry);
|
|
|
|
Label exit(env);
|
|
|
|
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
|
|
|
Label notOnProtoChain(env);
|
|
|
|
Branch(Int64NotEqual(receiver, holder), &exit, ¬OnProtoChain);
|
|
|
|
Bind(¬OnProtoChain);
|
|
|
|
|
|
|
|
auto negativeZero = GetGlobalConstantValue(
|
|
|
|
VariableType::JS_POINTER(), glue, ConstantIndex::NEGATIVE_ZERO_STRING_INDEX);
|
|
|
|
Label isNegativeZero(env);
|
|
|
|
Label notNegativeZero(env);
|
|
|
|
Branch(Int64Equal(negativeZero, key), &isNegativeZero, ¬NegativeZero);
|
|
|
|
Bind(&isNegativeZero);
|
|
|
|
{
|
|
|
|
Label isObj(env);
|
|
|
|
Label notObj(env);
|
2022-08-08 13:05:10 +00:00
|
|
|
Branch(IsEcmaObject(value), &isObj, ¬Obj);
|
2022-06-10 07:33:31 +00:00
|
|
|
Bind(&isObj);
|
|
|
|
{
|
|
|
|
result = Null();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬Obj);
|
|
|
|
result = Undefined();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬NegativeZero);
|
|
|
|
{
|
|
|
|
GateRef index = TryStringOrSymbelToElementIndex(key);
|
|
|
|
Label validIndex(env);
|
|
|
|
Label notValidIndex(env);
|
|
|
|
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, ¬ValidIndex);
|
|
|
|
Bind(&validIndex);
|
|
|
|
{
|
|
|
|
result = CallRuntime(glue, RTSTUB_ID(SetTypeArrayPropertyByIndex),
|
2022-08-29 07:10:59 +00:00
|
|
|
{ receiver, IntToTaggedInt(index), value, IntToTaggedInt(jsType) });
|
2022-06-10 07:33:31 +00:00
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
Bind(¬ValidIndex);
|
|
|
|
{
|
|
|
|
Label returnNull(env);
|
|
|
|
Branch(Int32Equal(index, Int32(-2)), &returnNull, &exit); // -2:equal -2 means should goto slow path
|
|
|
|
Bind(&returnNull);
|
|
|
|
{
|
|
|
|
result = Null();
|
|
|
|
Jump(&exit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Bind(&exit);
|
|
|
|
auto ret = *result;
|
|
|
|
env->SubCfgExit();
|
|
|
|
return ret;
|
|
|
|
}
|
2021-12-23 06:55:22 +00:00
|
|
|
} // namespace panda::ecmascript::kungfu
|