mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 16:13:49 +00:00
!5828 Reuse StObjByValue IC to add StOwnByIndex IC
Merge pull request !5828 from YuliCheng/StOwnByIndex
This commit is contained in:
commit
aafa9df6bb
@ -230,6 +230,45 @@ GateRef AccessObjectStubBuilder::StoreObjByValue(GateRef glue, GateRef receiver,
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef AccessObjectStubBuilder::StoreOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value,
|
||||
GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entry(env);
|
||||
env->SubCfgEntry(&entry);
|
||||
Label exit(env);
|
||||
Label tryFastPath(env);
|
||||
Label slowPath(env);
|
||||
Label isHeapObject(env);
|
||||
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
|
||||
ICStubBuilder builder(this);
|
||||
builder.SetParameters(glue, receiver, profileTypeInfo, value, slotId, IntToTaggedPtr(index), callback);
|
||||
builder.StoreICByValue(&result, &tryFastPath, &slowPath, &exit);
|
||||
Bind(&tryFastPath);
|
||||
{
|
||||
Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
|
||||
Bind(&isHeapObject);
|
||||
Label notClassConstructor(env);
|
||||
Branch(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor);
|
||||
Bind(¬ClassConstructor);
|
||||
Label notClassPrototype(env);
|
||||
Branch(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype);
|
||||
Bind(¬ClassPrototype);
|
||||
result = SetPropertyByIndex(glue, receiver, index, value, true);
|
||||
Branch(TaggedIsHole(*result), &slowPath, &exit);
|
||||
}
|
||||
Bind(&slowPath);
|
||||
{
|
||||
result = CallRuntime(glue, RTSTUB_ID(StOwnByIndex), { receiver, IntToTaggedInt(index), value });
|
||||
callback.TryPreDump();
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef AccessObjectStubBuilder::TryLoadGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef profileTypeInfo, GateRef slotId,
|
||||
ProfileOperation callback)
|
||||
|
@ -42,6 +42,8 @@ public:
|
||||
ProfileOperation callback = ProfileOperation());
|
||||
GateRef StoreObjByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, GateRef profileTypeInfo,
|
||||
GateRef slotId, ProfileOperation callback = ProfileOperation());
|
||||
GateRef StoreOwnByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, GateRef profileTypeInfo,
|
||||
GateRef slotId, ProfileOperation callback = ProfileOperation());
|
||||
GateRef DeprecatedLoadObjByValue(GateRef glue, GateRef receiver, GateRef key);
|
||||
GateRef TryLoadGlobalByName(GateRef glue, GateRef prop, const StringIdInfo &info,
|
||||
GateRef profileTypeInfo, GateRef slotId, ProfileOperation callback);
|
||||
|
@ -242,7 +242,6 @@ void ICStubBuilder::StoreICByValue(Variable* result, Label* tryFastPath, Label *
|
||||
auto env = GetEnvironment();
|
||||
Label storeWithHandler(env);
|
||||
Label storeElement(env);
|
||||
|
||||
SetLabels(tryFastPath, slowPath, success);
|
||||
GateRef secondValue = GetValueFromTaggedArray(
|
||||
profileTypeInfo_, Int32Add(slotId_, Int32(1)));
|
||||
|
@ -1751,70 +1751,30 @@ DECLARE_ASM_HANDLER(HandleWideStobjbyindexPrefV8Imm32)
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleStownbyindexImm16V8Imm16)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef v0 = ReadInst8_2(pc);
|
||||
GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0));
|
||||
GateRef index = ZExtInt16ToInt32(ReadInst16_3(pc));
|
||||
Label isHeapObject(env);
|
||||
Label slowPath(env);
|
||||
Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
|
||||
Bind(&isHeapObject);
|
||||
Label notClassConstructor(env);
|
||||
Branch(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor);
|
||||
Bind(¬ClassConstructor);
|
||||
Label notClassPrototype(env);
|
||||
Branch(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype);
|
||||
Bind(¬ClassPrototype);
|
||||
{
|
||||
// fast path
|
||||
GateRef result = SetPropertyByIndex(glue, receiver, index, acc, true); // acc is value
|
||||
Label notHole(env);
|
||||
Branch(TaggedIsHole(result), &slowPath, ¬Hole);
|
||||
Bind(¬Hole);
|
||||
CHECK_EXCEPTION(result, INT_PTR(STOWNBYINDEX_IMM16_V8_IMM16));
|
||||
}
|
||||
Bind(&slowPath);
|
||||
{
|
||||
GateRef result = CallRuntime(glue, RTSTUB_ID(StOwnByIndex),
|
||||
{ receiver, IntToTaggedInt(index), acc });
|
||||
CHECK_EXCEPTION(result, INT_PTR(STOWNBYINDEX_IMM16_V8_IMM16));
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleStownbyindexImm8V8Imm16)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
GateRef v0 = ReadInst8_1(pc);
|
||||
GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0));
|
||||
GateRef index = ZExtInt16ToInt32(ReadInst16_2(pc));
|
||||
Label isHeapObject(env);
|
||||
Label slowPath(env);
|
||||
Branch(TaggedIsHeapObject(receiver), &isHeapObject, &slowPath);
|
||||
Bind(&isHeapObject);
|
||||
Label notClassConstructor(env);
|
||||
Branch(IsClassConstructor(receiver), &slowPath, ¬ClassConstructor);
|
||||
Bind(¬ClassConstructor);
|
||||
Label notClassPrototype(env);
|
||||
Branch(IsClassPrototype(receiver), &slowPath, ¬ClassPrototype);
|
||||
Bind(¬ClassPrototype);
|
||||
{
|
||||
// fast path
|
||||
GateRef result = SetPropertyByIndex(glue, receiver, index, acc, true); // acc is value
|
||||
Label notHole(env);
|
||||
Branch(TaggedIsHole(result), &slowPath, ¬Hole);
|
||||
Bind(¬Hole);
|
||||
CHECK_EXCEPTION(result, INT_PTR(STOWNBYINDEX_IMM8_V8_IMM16));
|
||||
}
|
||||
Bind(&slowPath);
|
||||
{
|
||||
GateRef result = CallRuntime(glue, RTSTUB_ID(StOwnByIndex),
|
||||
{ receiver, IntToTaggedInt(index), acc });
|
||||
CHECK_EXCEPTION(result, INT_PTR(STOWNBYINDEX_IMM8_V8_IMM16));
|
||||
}
|
||||
GateRef value = acc;
|
||||
GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc));
|
||||
|
||||
AccessObjectStubBuilder builder(this);
|
||||
GateRef result = builder.StoreOwnByIndex(glue, receiver, index, value, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION(result, INT_PTR(STOWNBYINDEX_IMM8_V8_IMM16));
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleStownbyindexImm16V8Imm16)
|
||||
{
|
||||
GateRef v0 = ReadInst8_2(pc);
|
||||
GateRef receiver = GetVregValue(sp, ZExtInt8ToPtr(v0));
|
||||
GateRef index = ZExtInt16ToInt32(ReadInst16_3(pc));
|
||||
GateRef value = acc;
|
||||
GateRef slotId = ZExtInt16ToInt32(ReadInst16_0(pc));
|
||||
|
||||
AccessObjectStubBuilder builder(this);
|
||||
GateRef result = builder.StoreOwnByIndex(glue, receiver, index, value, profileTypeInfo, slotId, callback);
|
||||
CHECK_EXCEPTION(result, INT_PTR(STOWNBYINDEX_IMM16_V8_IMM16));
|
||||
}
|
||||
|
||||
DECLARE_ASM_HANDLER(HandleWideStownbyindexPrefV8Imm32)
|
||||
|
@ -311,7 +311,7 @@ JSTaggedValue LoadICRuntime::LoadTypedArrayValueMiss(JSHandle<JSTaggedValue> rec
|
||||
}
|
||||
|
||||
JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value)
|
||||
JSHandle<JSTaggedValue> value, bool isOwn)
|
||||
{
|
||||
if (!receiver->IsJSObject() || receiver->HasOrdinaryGet()) {
|
||||
icAccessor_.SetAsMega();
|
||||
@ -322,7 +322,6 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHand
|
||||
if (receiver->IsTypedArray()) {
|
||||
return StoreTypedArrayValueMiss(receiver, key, value);
|
||||
}
|
||||
|
||||
ICKind kind = GetICKind();
|
||||
// global variable find from global record firstly
|
||||
if (kind == ICKind::NamedGlobalStoreIC || kind == ICKind::NamedGlobalTryStoreIC) {
|
||||
@ -338,8 +337,7 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHand
|
||||
}
|
||||
}
|
||||
UpdateReceiverHClass(JSHandle<JSTaggedValue>(GetThread(), JSHandle<JSObject>::Cast(receiver)->GetClass()));
|
||||
|
||||
ObjectOperator op(GetThread(), receiver, key);
|
||||
ObjectOperator op = ConstructOp(receiver, key, value, isOwn);
|
||||
if (!op.IsFound()) {
|
||||
if (kind == ICKind::NamedGlobalStoreIC) {
|
||||
PropertyAttributes attr = PropertyAttributes::Default(true, true, false);
|
||||
|
@ -56,6 +56,20 @@ public:
|
||||
return icAccessor_.GetKind();
|
||||
}
|
||||
|
||||
ObjectOperator ConstructOp(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value, bool isOwn) const
|
||||
{
|
||||
ObjectOperator op(GetThread(), receiver, key,
|
||||
isOwn ? OperatorType::OWN : OperatorType::PROTOTYPE_CHAIN);
|
||||
if (isOwn) {
|
||||
bool enumerable = !(receiver->IsClassPrototype() || receiver->IsClassConstructor());
|
||||
PropertyDescriptor desc(GetThread(), value, true, enumerable, true);
|
||||
PropertyAttributes attr(desc);
|
||||
op.SetAttr(attr);
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
void TraceIC(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key) const;
|
||||
|
||||
protected:
|
||||
@ -88,7 +102,8 @@ public:
|
||||
~StoreICRuntime() = default;
|
||||
|
||||
JSTaggedValue StoreMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value);
|
||||
JSHandle<JSTaggedValue> value, bool isOwn = false);
|
||||
|
||||
JSTaggedValue StoreTypedArrayValueMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value);
|
||||
};
|
||||
|
@ -179,6 +179,14 @@ ARK_NOINLINE JSTaggedValue ICRuntimeStub::StoreICByValue(JSThread *thread, Profi
|
||||
return StoreMiss(thread, profileTypeInfo, receiver, key, value, slotId, ICKind::StoreIC);
|
||||
}
|
||||
|
||||
ARK_NOINLINE JSTaggedValue ICRuntimeStub::StoreOwnICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
||||
JSTaggedValue receiver, JSTaggedValue key,
|
||||
JSTaggedValue value, uint32_t slotId)
|
||||
{
|
||||
INTERPRETER_TRACE(thread, StoreOwnICByValue);
|
||||
return StoreMiss(thread, profileTypeInfo, receiver, key, value, slotId, ICKind::StoreIC, true);
|
||||
}
|
||||
|
||||
ARK_INLINE JSTaggedValue ICRuntimeStub::TryStoreICByName(JSThread *thread, JSTaggedValue receiver,
|
||||
JSTaggedValue firstValue, JSTaggedValue secondValue,
|
||||
JSTaggedValue value)
|
||||
@ -645,7 +653,7 @@ JSTaggedValue ICRuntimeStub::LoadValueMiss(JSThread *thread, ProfileTypeInfo *pr
|
||||
}
|
||||
|
||||
JSTaggedValue ICRuntimeStub::StoreMiss(JSThread *thread, ProfileTypeInfo *profileTypeInfo, JSTaggedValue receiver,
|
||||
JSTaggedValue key, JSTaggedValue value, uint32_t slotId, ICKind kind)
|
||||
JSTaggedValue key, JSTaggedValue value, uint32_t slotId, ICKind kind, bool isOwn)
|
||||
{
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
auto keyHandle = JSHandle<JSTaggedValue>(thread, key);
|
||||
@ -653,7 +661,7 @@ JSTaggedValue ICRuntimeStub::StoreMiss(JSThread *thread, ProfileTypeInfo *profil
|
||||
auto valueHandle = JSHandle<JSTaggedValue>(thread, value);
|
||||
auto profileInfoHandle = JSHandle<JSTaggedValue>(thread, profileTypeInfo);
|
||||
StoreICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileInfoHandle), slotId, kind);
|
||||
return icRuntime.StoreMiss(receiverHandle, keyHandle, valueHandle);
|
||||
return icRuntime.StoreMiss(receiverHandle, keyHandle, valueHandle, isOwn);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
@ -70,6 +70,9 @@ public:
|
||||
static inline JSTaggedValue StoreICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
||||
JSTaggedValue receiver, JSTaggedValue key, JSTaggedValue value,
|
||||
uint32_t slotId);
|
||||
static inline JSTaggedValue StoreOwnICByValue(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
||||
JSTaggedValue receiver, JSTaggedValue key,
|
||||
JSTaggedValue value, uint32_t slotId);
|
||||
static inline JSTaggedValue LoadElement(JSObject *receiver, JSTaggedValue key);
|
||||
static inline JSTaggedValue LoadStringElement(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key);
|
||||
static inline JSTaggedValue LoadTypedArrayElement(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key);
|
||||
@ -83,7 +86,8 @@ public:
|
||||
static inline JSTaggedValue LoadValueMiss(JSThread *thread, ProfileTypeInfo *profileTypeInfo,
|
||||
JSTaggedValue receiver, JSTaggedValue key, uint32_t slotId, ICKind kind);
|
||||
static inline JSTaggedValue StoreMiss(JSThread *thread, ProfileTypeInfo *profileTypeInfo, JSTaggedValue receiver,
|
||||
JSTaggedValue key, JSTaggedValue value, uint32_t slotId, ICKind kind);
|
||||
JSTaggedValue key, JSTaggedValue value, uint32_t slotId,
|
||||
ICKind kind, bool isOwn = false);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
@ -5700,12 +5700,39 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
|
||||
HANDLE_OPCODE(STOWNBYINDEX_IMM8_V8_IMM16) {
|
||||
uint8_t v0 = READ_INST_8_1();
|
||||
uint16_t index = READ_INST_16_2();
|
||||
JSTaggedValue receiver = GET_VREG_VALUE(v0);
|
||||
LOG_INST() << "intrinsics::stownbyindex"
|
||||
<< " v" << v0 << " imm" << index;
|
||||
JSTaggedValue receiver = GET_VREG_VALUE(v0);
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
|
||||
if (!profileTypeInfo.IsUndefined()) {
|
||||
SAVE_ACC();
|
||||
uint32_t slotId = READ_INST_8_0();
|
||||
auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject());
|
||||
JSTaggedValue firstValue = profileTypeArray->Get(slotId);
|
||||
JSTaggedValue value = GET_ACC();
|
||||
JSTaggedValue res = JSTaggedValue::Hole();
|
||||
if (LIKELY(firstValue.IsHeapObject())) {
|
||||
JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1);
|
||||
res = ICRuntimeStub::TryStoreICByValue(thread,
|
||||
receiver, JSTaggedValue(index), firstValue, secondValue, value);
|
||||
}
|
||||
// IC miss and not enter the megamorphic state, store as polymorphic
|
||||
if (res.IsHole() && !firstValue.IsHole()) {
|
||||
res = ICRuntimeStub::StoreOwnICByValue(thread,
|
||||
profileTypeArray, receiver, JSTaggedValue(index), value, slotId);
|
||||
}
|
||||
if (LIKELY(!res.IsHole())) {
|
||||
INTERPRETER_RETURN_IF_ABRUPT(res);
|
||||
RESTORE_ACC();
|
||||
DISPATCH(STOWNBYINDEX_IMM8_V8_IMM16);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// fast path
|
||||
if (receiver.IsHeapObject() && !receiver.IsClassConstructor() && !receiver.IsClassPrototype()) {
|
||||
SAVE_ACC();
|
||||
receiver = GET_VREG_VALUE(v0);
|
||||
JSTaggedValue value = GET_ACC();
|
||||
// fast path
|
||||
JSTaggedValue res = FastRuntimeStub::SetPropertyByIndex<ObjectFastOperator::Status::UseOwn>
|
||||
@ -5732,6 +5759,33 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
|
||||
LOG_INST() << "intrinsics::stownbyindex"
|
||||
<< " v" << v0 << " imm" << index;
|
||||
JSTaggedValue receiver = GET_VREG_VALUE(v0);
|
||||
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
|
||||
if (!profileTypeInfo.IsUndefined()) {
|
||||
SAVE_ACC();
|
||||
uint16_t slotId = READ_INST_16_0();
|
||||
auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject());
|
||||
JSTaggedValue firstValue = profileTypeArray->Get(slotId);
|
||||
JSTaggedValue value = GET_ACC();
|
||||
JSTaggedValue res = JSTaggedValue::Hole();
|
||||
if (LIKELY(firstValue.IsHeapObject())) {
|
||||
JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1);
|
||||
res = ICRuntimeStub::TryStoreICByValue(thread,
|
||||
receiver, JSTaggedValue(index), firstValue, secondValue, value);
|
||||
}
|
||||
// IC miss and not enter the megamorphic state, store as polymorphic
|
||||
if (res.IsHole() && !firstValue.IsHole()) {
|
||||
res = ICRuntimeStub::StoreOwnICByValue(thread,
|
||||
profileTypeArray, receiver, JSTaggedValue(index), value, slotId);
|
||||
}
|
||||
if (LIKELY(!res.IsHole())) {
|
||||
INTERPRETER_RETURN_IF_ABRUPT(res);
|
||||
RESTORE_ACC();
|
||||
DISPATCH(STOWNBYINDEX_IMM16_V8_IMM16);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// fast path
|
||||
if (receiver.IsHeapObject() && !receiver.IsClassConstructor() && !receiver.IsClassPrototype()) {
|
||||
SAVE_ACC();
|
||||
|
@ -139,6 +139,7 @@ namespace panda::ecmascript {
|
||||
V(TryLoadICByValue) \
|
||||
V(LoadICByValue) \
|
||||
V(TryStoreICByName) \
|
||||
V(StoreOwnICByValue) \
|
||||
V(StoreICByName) \
|
||||
V(TryStoreICByValue) \
|
||||
V(StoreICByValue) \
|
||||
|
@ -1088,6 +1088,24 @@ DEF_RUNTIME_STUBS(StoreICByValue)
|
||||
return icRuntime.StoreMiss(receiver, propKey, value).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(StoreOwnICByValue)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(StoreOwnICByValue);
|
||||
JSHandle<JSTaggedValue> profileTypeInfo = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSHandle<JSTaggedValue> receiver = GetHArg<JSTaggedValue>(argv, argc, 1); // 1: means the first parameter
|
||||
JSHandle<JSTaggedValue> key = GetHArg<JSTaggedValue>(argv, argc, 2); // 2: means the second parameter
|
||||
JSHandle<JSTaggedValue> value = GetHArg<JSTaggedValue>(argv, argc, 3); // 3: means the third parameter
|
||||
JSTaggedValue slotId = GetArg(argv, argc, 4); // 4: means the fourth parameter
|
||||
if (profileTypeInfo->IsUndefined()) {
|
||||
return RuntimeStOwnByIndex(thread, receiver, key, value).GetRawData();
|
||||
}
|
||||
JSHandle<JSTaggedValue> propKey = JSTaggedValue::ToPropertyKey(thread, key);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception().GetRawData());
|
||||
StoreICRuntime icRuntime(thread, JSHandle<ProfileTypeInfo>::Cast(profileTypeInfo), slotId.GetInt(),
|
||||
ICKind::StoreIC);
|
||||
return icRuntime.StoreMiss(receiver, propKey, value, true).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(StOwnByValue)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(StOwnByValue);
|
||||
|
@ -229,6 +229,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(SetObjectWithProto) \
|
||||
V(LoadICByValue) \
|
||||
V(StoreICByValue) \
|
||||
V(StoreOwnICByValue) \
|
||||
V(StOwnByValue) \
|
||||
V(LdSuperByValue) \
|
||||
V(StSuperByValue) \
|
||||
|
@ -15,3 +15,27 @@
|
||||
123
|
||||
2
|
||||
2.1
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
99.99
|
||||
ark
|
||||
-88.48
|
||||
brk
|
||||
-1024
|
||||
crk
|
||||
6666
|
||||
drk
|
||||
in 1 second,now,now,1 second ago
|
||||
in 1 minute,this minute,this minute,1 minute ago
|
||||
2
|
||||
ok
|
||||
1
|
||||
2
|
||||
3
|
||||
yes
|
||||
no
|
||||
4
|
||||
5
|
||||
|
@ -33,12 +33,137 @@ function foo(p) {
|
||||
return p[1]
|
||||
}
|
||||
|
||||
let a = [1, 2]
|
||||
let b = [1, 2.1, 3]
|
||||
for (let i = 0; i < 100000; i++) {
|
||||
var a1 = foo(a)
|
||||
var a2 = foo(b);
|
||||
{
|
||||
let a = [1, 2]
|
||||
let b = [1, 2.1, 3]
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
var a1 = foo(a)
|
||||
var a2 = foo(b);
|
||||
}
|
||||
print(a1)
|
||||
print(a2)
|
||||
}
|
||||
print(a1)
|
||||
print(a2)
|
||||
|
||||
// test stownbyindex ic: (too many loop will fail at debug unittest timeout)
|
||||
class Attrs {
|
||||
constructor(a : number, b : number, c : number) {
|
||||
this.x = a;
|
||||
this.y = b;
|
||||
this.z = c;
|
||||
}
|
||||
x : number;
|
||||
y : number;
|
||||
z : number;
|
||||
}
|
||||
|
||||
function test() : void {
|
||||
for (let j = 0; j < 5; ++j) {
|
||||
var _attrs : Attrs[] = [
|
||||
new Attrs(1, 1, 1),
|
||||
new Attrs(2, 2, 2),
|
||||
new Attrs(3, 3, 3),
|
||||
new Attrs(4, 4, 4),
|
||||
new Attrs(5, 5, 5),
|
||||
];
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < 100; i++){
|
||||
test();
|
||||
}
|
||||
|
||||
for (let j = 0; j < 5; ++j) {
|
||||
var _attrs : Attrs[] = [
|
||||
new Attrs(1, 1, 1),
|
||||
new Attrs(2, 2, 2),
|
||||
new Attrs(3, 3, 3),
|
||||
new Attrs(4, 4, 4),
|
||||
new Attrs(5, 5, 5),
|
||||
];
|
||||
print(_attrs[j].x);
|
||||
}
|
||||
|
||||
|
||||
const tests = [
|
||||
[99.99, "ark"],
|
||||
[-88.48, "brk"],
|
||||
[-1024, "crk"],
|
||||
[6666, "drk"],
|
||||
];
|
||||
|
||||
for (let i = 0; i < 100; i++){
|
||||
for (const [number, strData] of tests) {
|
||||
}
|
||||
}
|
||||
|
||||
for (const [number, strData] of tests) {
|
||||
print(number);
|
||||
print(strData);
|
||||
}
|
||||
|
||||
const exceptions = {
|
||||
"minute" : {
|
||||
"-1" : "1 minute ago",
|
||||
'0' : 'this minute',
|
||||
"1" : "in 1 minute",
|
||||
},
|
||||
"second" : {
|
||||
"-1" : "1 second ago",
|
||||
"0" : "now",
|
||||
"1" : "in 1 second",
|
||||
},
|
||||
};
|
||||
|
||||
const units = [
|
||||
"second",
|
||||
"minute",
|
||||
];
|
||||
|
||||
for (let i = 0; i < 100; i++){
|
||||
for (const unit of units) {
|
||||
const expected = unit in exceptions ?
|
||||
[exceptions[unit]["1"], exceptions[unit]["0"], exceptions[unit]["0"], exceptions[unit]["-1"]] :
|
||||
[`in 1 ${unit}`, `in 0 ${unit}s`, `0 ${unit}s ago`, `1 ${unit} ago`];
|
||||
}
|
||||
}
|
||||
|
||||
for (const unit of units) {
|
||||
const expected = unit in exceptions ?
|
||||
[exceptions[unit]["1"], exceptions[unit]["0"], exceptions[unit]["0"], exceptions[unit]["-1"]] :
|
||||
[`in 1 ${unit}`, `in 0 ${unit}s`, `0 ${unit}s ago`, `1 ${unit} ago`];
|
||||
|
||||
print(expected);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 100; i++){
|
||||
Object.defineProperty(Array.prototype, '0', {
|
||||
value: 42,
|
||||
});
|
||||
let arr = [, 2, 3];
|
||||
arr.pop();
|
||||
}
|
||||
|
||||
Object.defineProperty(Array.prototype, '0', {
|
||||
value: 42,
|
||||
});
|
||||
let arr = [, 2, 3];
|
||||
arr.pop();
|
||||
print(arr[1]);
|
||||
|
||||
for (let i = 0; i < 100; i++){
|
||||
var a : any[] = [ ["ok"], [1, 2, 3] ];
|
||||
var b = {
|
||||
1 : ["yes", "no"],
|
||||
"100" : [4, 5],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
print(a[0][0]);
|
||||
print(a[1][0]);
|
||||
print(a[1][1]);
|
||||
print(a[1][2]);
|
||||
|
||||
print(b[1][0]);
|
||||
print(b[1][1]);
|
||||
print(b["100"][0]);
|
||||
print(b["100"][1]);
|
Loading…
Reference in New Issue
Block a user