mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 04:00:37 +00:00
Add Instanceof IC
issues:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I647H9 Signed-off-by: lvfuqing <lvfuqing1@huawei.com> Change-Id: I535da661f62985d7147ab5fd57830011b5c55765
This commit is contained in:
parent
7f56f31591
commit
4751856dfb
@ -2037,10 +2037,45 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
|
||||
uint16_t v0 = READ_INST_8_1();
|
||||
LOG_INST() << "intrinsics::instanceof"
|
||||
<< " v" << v0;
|
||||
JSTaggedValue obj = GET_VREG_VALUE(v0);
|
||||
JSTaggedValue object = GET_VREG_VALUE(v0);
|
||||
JSTaggedValue target = GET_ACC();
|
||||
|
||||
#if ECMASCRIPT_ENABLE_IC
|
||||
// 1. If Type(target) is not Object, throw a TypeError exception.
|
||||
if (target.IsECMAObject()) {
|
||||
// 2. Let instOfHandler be GetMethod(target, @@hasInstance).
|
||||
auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
|
||||
if (!profileTypeInfo.IsUndefined()) {
|
||||
uint16_t slotId = READ_INST_8_0();
|
||||
auto profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject());
|
||||
JSTaggedValue firstValue = profileTypeArray->Get(slotId);
|
||||
JSTaggedValue instOfHandler = JSTaggedValue::Hole();
|
||||
JSTaggedValue res = JSTaggedValue::Hole();
|
||||
if (LIKELY(firstValue.IsHeapObject())) {
|
||||
JSTaggedValue secondValue = profileTypeArray->Get(slotId + 1);
|
||||
instOfHandler = ICRuntimeStub::TryLoadICByName(thread, target, firstValue, secondValue);
|
||||
}
|
||||
if (LIKELY(!instOfHandler.IsHole())) {
|
||||
res = SlowRuntimeStub::InstanceofByHandler(thread, target, object, instOfHandler);
|
||||
} else if (!firstValue.IsHole()) {
|
||||
// IC Miss
|
||||
profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
|
||||
profileTypeArray = ProfileTypeInfo::Cast(profileTypeInfo.GetTaggedObject());
|
||||
EcmaVM *vm = thread->GetEcmaVM();
|
||||
JSTaggedValue key = vm->GetGlobalEnv()->GetHasInstanceSymbol().GetTaggedValue();
|
||||
instOfHandler = ICRuntimeStub::LoadICByName(thread, profileTypeArray, target, key, slotId);
|
||||
res = SlowRuntimeStub::InstanceofByHandler(thread, target, object, instOfHandler);
|
||||
}
|
||||
if (LIKELY(!res.IsHole())) {
|
||||
INTERPRETER_RETURN_IF_ABRUPT(res);
|
||||
SET_ACC(res);
|
||||
DISPATCH(INSTANCEOF_IMM8_V8);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
SAVE_PC();
|
||||
JSTaggedValue res = SlowRuntimeStub::Instanceof(thread, obj, target);
|
||||
JSTaggedValue res = SlowRuntimeStub::Instanceof(thread, object, target);
|
||||
INTERPRETER_RETURN_IF_ABRUPT(res);
|
||||
SET_ACC(res);
|
||||
DISPATCH(INSTANCEOF_IMM8_V8);
|
||||
|
@ -388,6 +388,19 @@ JSTaggedValue SlowRuntimeStub::Instanceof(JSThread *thread, JSTaggedValue obj, J
|
||||
return RuntimeStubs::RuntimeInstanceof(thread, objHandle, targetHandle);
|
||||
}
|
||||
|
||||
JSTaggedValue SlowRuntimeStub::InstanceofByHandler(JSThread *thread, JSTaggedValue target, JSTaggedValue object,
|
||||
JSTaggedValue instOfHandler)
|
||||
{
|
||||
INTERPRETER_TRACE(thread, InstanceofByHandler);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
|
||||
JSHandle<JSTaggedValue> objectHandle(thread, object);
|
||||
JSHandle<JSTaggedValue> targetHandle(thread, target);
|
||||
JSHandle<JSTaggedValue> instOfHandle(thread, instOfHandler);
|
||||
|
||||
return RuntimeStubs::RuntimeInstanceofByHandler(thread, targetHandle, objectHandle, instOfHandle);
|
||||
}
|
||||
|
||||
JSTaggedValue SlowRuntimeStub::NewLexicalEnv(JSThread *thread, uint16_t numVars)
|
||||
{
|
||||
INTERPRETER_TRACE(thread, Newlexenv);
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
static JSTaggedValue Exp(JSThread *thread, JSTaggedValue base, JSTaggedValue exponent);
|
||||
static JSTaggedValue IsIn(JSThread *thread, JSTaggedValue prop, JSTaggedValue obj);
|
||||
static JSTaggedValue Instanceof(JSThread *thread, JSTaggedValue obj, JSTaggedValue target);
|
||||
static JSTaggedValue InstanceofByHandler(JSThread *thread, JSTaggedValue target, JSTaggedValue object,
|
||||
JSTaggedValue instOfHandler);
|
||||
|
||||
static JSTaggedValue NewLexicalEnv(JSThread *thread, uint16_t numVars);
|
||||
static JSTaggedValue NewLexicalEnvWithName(JSThread *thread, uint16_t numVars, uint16_t scopeId);
|
||||
|
@ -1391,6 +1391,8 @@ void PandaFileTranslator::UpdateICOffset(MethodLiteral *methodLiteral, uint8_t *
|
||||
case EcmaOpcode::STGLOBALVAR_IMM16_ID16:
|
||||
offset = methodLiteral->UpdateSlotSizeWith8Bit(1);
|
||||
break;
|
||||
case EcmaOpcode::INSTANCEOF_IMM8_V8:
|
||||
U_FALLTHROUGH;
|
||||
case EcmaOpcode::STOBJBYVALUE_IMM8_V8_V8:
|
||||
U_FALLTHROUGH;
|
||||
case EcmaOpcode::STOWNBYVALUE_IMM8_V8_V8:
|
||||
|
@ -84,6 +84,7 @@ namespace panda::ecmascript {
|
||||
V(Ldnewobjrange) \
|
||||
V(IsIn) \
|
||||
V(Instanceof) \
|
||||
V(InstanceofByHandler) \
|
||||
V(NewObjApply) \
|
||||
V(CallArg0) \
|
||||
V(CallArg1) \
|
||||
|
@ -124,6 +124,34 @@ JSTaggedValue RuntimeStubs::RuntimeInstanceof(JSThread *thread, const JSHandle<J
|
||||
return JSTaggedValue(ret);
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeInstanceofByHandler(JSThread *thread, JSHandle<JSTaggedValue> target,
|
||||
JSHandle<JSTaggedValue> object,
|
||||
JSHandle<JSTaggedValue> instOfHandler)
|
||||
{
|
||||
// 3. ReturnIfAbrupt(instOfHandler).
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue(false));
|
||||
|
||||
// 4. If instOfHandler is not undefined, then
|
||||
if (!instOfHandler->IsUndefined()) {
|
||||
// a. Return ! ToBoolean(? Call(instOfHandler, target, «object»)).
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, instOfHandler, target, undefined, 1);
|
||||
info->SetCallArg(object.GetTaggedValue());
|
||||
JSTaggedValue tagged = JSFunction::Call(info);
|
||||
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue(false));
|
||||
return tagged;
|
||||
}
|
||||
|
||||
// 5. If IsCallable(target) is false, throw a TypeError exception.
|
||||
if (!target->IsCallable()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "InstanceOf error when target is not Callable", JSTaggedValue(false));
|
||||
}
|
||||
|
||||
// 6. Return ? OrdinaryHasInstance(target, object).
|
||||
bool res = JSFunction::OrdinaryHasInstance(thread, target, object);
|
||||
return JSTaggedValue(res);
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeCreateGeneratorObj(JSThread *thread, const JSHandle<JSTaggedValue> &genFunc)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
@ -352,9 +352,12 @@ private:
|
||||
static inline JSTaggedValue RuntimeDec(JSThread *thread, const JSHandle<JSTaggedValue> &value);
|
||||
static inline JSTaggedValue RuntimeExp(JSThread *thread, JSTaggedValue base, JSTaggedValue exponent);
|
||||
static inline JSTaggedValue RuntimeIsIn(JSThread *thread, const JSHandle<JSTaggedValue> &prop,
|
||||
const JSHandle<JSTaggedValue> &obj);
|
||||
const JSHandle<JSTaggedValue> &obj);
|
||||
static inline JSTaggedValue RuntimeInstanceof(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
|
||||
const JSHandle<JSTaggedValue> &target);
|
||||
const JSHandle<JSTaggedValue> &target);
|
||||
static inline JSTaggedValue RuntimeInstanceofByHandler(JSThread *thread, JSHandle<JSTaggedValue> target,
|
||||
JSHandle<JSTaggedValue> object,
|
||||
JSHandle<JSTaggedValue> instOfHandler);
|
||||
static inline JSTaggedValue RuntimeCreateGeneratorObj(JSThread *thread, const JSHandle<JSTaggedValue> &genFunc);
|
||||
|
||||
static inline JSTaggedValue RuntimeCreateAsyncGeneratorObj(JSThread *thread,
|
||||
|
@ -38,6 +38,7 @@ group("ark_js_moduletest") {
|
||||
"globalrecord:globalrecordAction",
|
||||
"globalthis:globalthisAction",
|
||||
"helloworld:helloworldAction",
|
||||
"instanceofic:instanceoficAction",
|
||||
"ldmodulensbyic:ldmodulensbyicAction",
|
||||
"lexicalenv:lexicalenvAction",
|
||||
"linkedhashtable:linkedhashtableAction",
|
||||
@ -106,6 +107,7 @@ group("ark_asm_test") {
|
||||
"globalrecord:globalrecordAsmAction",
|
||||
"globalthis:globalthisAsmAction",
|
||||
"helloworld:helloworldAsmAction",
|
||||
"instanceofic:instanceoficAsmAction",
|
||||
"ldmodulensbyic:ldmodulensbyicAction",
|
||||
"lexicalenv:lexicalenvAsmAction",
|
||||
"linkedhashtable:linkedhashtableAsmAction",
|
||||
@ -166,6 +168,7 @@ group("ark_asm_single_step_test") {
|
||||
"globalrecord:globalrecordAsmSingleStepAction",
|
||||
"globalthis:globalthisAsmSingleStepAction",
|
||||
"helloworld:helloworldAsmSingleStepAction",
|
||||
"instanceofic:instanceoficAsmSingleStepAction",
|
||||
"ldmodulensbyic:ldmodulensbyicAction",
|
||||
"lexicalenv:lexicalenvAsmSingleStepAction",
|
||||
"loadicbyvalue:loadicbyvalueAsmSingleStepAction",
|
||||
|
18
test/moduletest/instanceofic/BUILD.gn
Normal file
18
test/moduletest/instanceofic/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# 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.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_moduletest_action("instanceofic") {
|
||||
deps = []
|
||||
}
|
15
test/moduletest/instanceofic/expect_output.txt
Normal file
15
test/moduletest/instanceofic/expect_output.txt
Normal file
@ -0,0 +1,15 @@
|
||||
# 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.
|
||||
|
||||
instanceoficsuccess
|
||||
instanceoficsuccess
|
47
test/moduletest/instanceofic/instanceofic.js
Normal file
47
test/moduletest/instanceofic/instanceofic.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @tc.name:instanceofic
|
||||
* @tc.desc:test instanceofic
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI5NO8G
|
||||
*/
|
||||
|
||||
class F {
|
||||
static [Symbol.hasInstance](instance) {
|
||||
return Array.isArray(instance);
|
||||
}
|
||||
};
|
||||
let res;
|
||||
|
||||
for (let i = 300; i > 0; --i) {
|
||||
res = [] instanceof F;
|
||||
if (i == 150) {
|
||||
if (res) {
|
||||
print("instanceoficsuccess");
|
||||
} else {
|
||||
print("instanceoficfailse");
|
||||
}
|
||||
F[Symbol.hasInstance] = function() { return false };
|
||||
}
|
||||
if (i == 140) {
|
||||
if (!res) {
|
||||
print("instanceoficsuccess");
|
||||
} else {
|
||||
print("instanceoficfailse");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user