AOT CopyRestArgs & GetUnMappedArgs fastpath

Issues: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I8YW81?from=project-issue
Signed-off-by: liuzhijie <liuzhijie9@huawei.com>

Change-Id: I6ba60df33116b48790361a2bf2ad78477ad6d3bc
This commit is contained in:
liuzhijie 2024-01-25 16:43:59 +08:00
parent 93b3b5faa0
commit 1409ae1994
20 changed files with 263 additions and 4 deletions

View File

@ -796,6 +796,22 @@ DEF_CALL_SIGNATURE(CreateArrayWithBuffer)
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(CopyRestArgs)
{
// 3 : 3 input parameters
CallSignature signature("CopyRestArgs", 0, 3,
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
*callSign = signature;
// 3 : 3 input parameters
std::array<VariableType, 3> params = {
VariableType::NATIVE_POINTER(), // glue
VariableType::INT32(), // startIdx
VariableType::INT32(), // numArgs
};
callSign->SetParameters(params.data());
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(NewJSObject)
{
// 2 : 2 input parameters

View File

@ -376,6 +376,7 @@ private:
V(TryStoreICByValue) \
V(SetValueWithBarrier) \
V(NewLexicalEnv) \
V(CopyRestArgs) \
V(GetUnmapedArgs) \
V(NewThisObjectChecked) \
V(ConstructorCheck) \

View File

@ -341,6 +341,7 @@ public:
GateRef CreateArray(ElementsKind kind, uint32_t arraySize, GateRef elementsLength);
GateRef CreateArrayWithBuffer(ElementsKind kind, ArrayMetaDataAccessor::Mode mode, GateRef cpId,
GateRef constPoolIndex, GateRef elementIndex);
GateRef CreateArguments(ElementsKind kind, CreateArgumentsAccessor::Mode mode, GateRef restIdx);
GateRef Construct(GateRef hirGate, std::vector<GateRef> args);
GateRef TypedCallNative(GateRef hirGate, GateRef thisObj, GateRef funcId);
GateRef IsBase(GateRef ctor);

View File

@ -288,6 +288,50 @@ void NewLexicalEnvStubBuilder::GenerateCircuit()
Return(*result);
}
void CopyRestArgsStubBuilder::GenerateCircuit()
{
DEFVARIABLE(argumentsList, VariableType::JS_ANY(), Undefined());
DEFVARIABLE(arrayObj, VariableType::JS_ANY(), Undefined());
DEFVARIABLE(actualRestNum, VariableType::INT32(), Int32(0));
auto env = GetEnvironment();
GateRef glue = PtrArgument(0);
GateRef startIdx = Int32Argument(1);
GateRef numArgs = Int32Argument(2);
Label afterArgumentsList(env);
Label newArgumentsObj(env);
Label numArgsGreater(env);
Label numArgsNotGreater(env);
GateRef argv = CallNGCRuntime(glue, RTSTUB_ID(GetActualArgvNoGC), { glue });
GateRef args = PtrAdd(argv, IntPtr(NUM_MANDATORY_JSFUNC_ARGS * 8)); // 8: ptr size
GateRef actualArgc = Int32Sub(numArgs, Int32(NUM_MANDATORY_JSFUNC_ARGS));
// 1. Calculate actual rest num.
Branch(Int32UnsignedGreaterThan(actualArgc, startIdx), &numArgsGreater, &numArgsNotGreater);
Bind(&numArgsGreater);
{
actualRestNum = Int32Sub(actualArgc, startIdx);
Jump(&numArgsNotGreater);
}
Bind(&numArgsNotGreater);
// 2. Construct arguments list.
NewObjectStubBuilder newBuilder(this);
newBuilder.SetParameters(glue, 0);
newBuilder.NewArgumentsList(&argumentsList, &afterArgumentsList, args, startIdx, *actualRestNum);
Bind(&afterArgumentsList);
// 3. Construct rest array.
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
GateRef arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
GateRef hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
arrayObj = newBuilder.NewJSArrayWithSize(hclass, *actualRestNum);
GateRef lengthOffset = IntPtr(JSArray::LENGTH_OFFSET);
Store(VariableType::INT32(), glue, *arrayObj, lengthOffset, *actualRestNum);
GateRef accessor = GetGlobalConstantValue(VariableType::JS_ANY(), glue, ConstantIndex::ARRAY_LENGTH_ACCESSOR);
SetPropertyInlinedProps(glue, *arrayObj, hclass, accessor, Int32(JSArray::LENGTH_INLINE_PROPERTY_INDEX));
SetExtensibleToBitfield(glue, *arrayObj, true);
SetElementsArray(VariableType::JS_POINTER(), glue, *arrayObj, *argumentsList);
Return(*arrayObj);
}
void GetUnmapedArgsStubBuilder::GenerateCircuit()
{
auto env = GetEnvironment();

View File

@ -77,6 +77,7 @@ namespace panda::ecmascript::kungfu {
V(TryStoreICByValue) \
V(SetValueWithBarrier) \
V(NewLexicalEnv) \
V(CopyRestArgs) \
V(GetUnmapedArgs) \
V(NewThisObjectChecked) \
V(ConstructorCheck) \

View File

@ -245,11 +245,19 @@ ArrayMetaDataAccessor GateAccessor::GetArrayMetaDataAccessor(GateRef gate) const
ASSERT(GetOpCode(gate) == OpCode::STABLE_ARRAY_CHECK ||
GetOpCode(gate) == OpCode::HCLASS_STABLE_ARRAY_CHECK ||
GetOpCode(gate) == OpCode::CREATE_ARRAY ||
GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER);
GetOpCode(gate) == OpCode::CREATE_ARRAY_WITH_BUFFER ||
GetOpCode(gate) == OpCode::CREATE_ARGUMENTS);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return ArrayMetaDataAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
}
CreateArgumentsAccessor GateAccessor::GetCreateArgumentsAccessor(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::CREATE_ARGUMENTS);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return CreateArgumentsAccessor(gatePtr->GetOneParameterMetaData()->GetValue());
}
ObjectTypeAccessor GateAccessor::GetObjectTypeAccessor(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::OBJECT_TYPE_CHECK ||

View File

@ -414,6 +414,7 @@ public:
TypedBinaryAccessor GetTypedBinaryAccessor(GateRef gate) const;
TypedJumpAccessor GetTypedJumpAccessor(GateRef gate) const;
ArrayMetaDataAccessor GetArrayMetaDataAccessor(GateRef gate) const;
CreateArgumentsAccessor GetCreateArgumentsAccessor(GateRef gate) const;
ObjectTypeAccessor GetObjectTypeAccessor(GateRef gate) const;
BuiltinPrototypeHClassAccessor GetBuiltinHClassAccessor(GateRef gate) const;
TypedArrayMetaDateAccessor GetTypedArrayMetaDateAccessor(GateRef gate) const;

View File

@ -437,6 +437,22 @@ GateRef CircuitBuilder::CreateArrayWithBuffer(ElementsKind kind, ArrayMetaDataAc
return newGate;
}
GateRef CircuitBuilder::CreateArguments(ElementsKind kind, CreateArgumentsAccessor::Mode mode, GateRef restIdx)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
CreateArgumentsAccessor accessor(kind, mode);
GateRef newGate = GetCircuit()->NewGate(circuit_->CreateArguments(accessor.ToValue()),
MachineType::I64,
{ currentControl, currentDepend, restIdx, frameState },
GateType::NJSValue());
currentLabel->SetControl(newGate);
currentLabel->SetDepend(newGate);
return newGate;
}
void CircuitBuilder::SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass,
GateRef value, GateRef attrOffset, VariableType type)
{

View File

@ -46,7 +46,8 @@ namespace panda::ecmascript::kungfu {
V(CallSetter, CALL_SETTER, GateFlags::HAS_FRAME_STATE, 1, 1, 4) \
V(MonoCallGetterOnProto, MONO_CALL_GETTER_ON_PROTO, GateFlags::HAS_FRAME_STATE, 1, 1, 4) \
V(CreateArray, CREATE_ARRAY, GateFlags::NONE_FLAG, 1, 1, 1) \
V(CreateArrayWithBuffer, CREATE_ARRAY_WITH_BUFFER, GateFlags::CHECKABLE, 1, 1, 3)
V(CreateArrayWithBuffer, CREATE_ARRAY_WITH_BUFFER, GateFlags::CHECKABLE, 1, 1, 3) \
V(CreateArguments, CREATE_ARGUMENTS, GateFlags::CHECKABLE, 1, 1, 1)
#define HCR_GATE_META_DATA_LIST_WITH_VALUE(V) \
V(RestoreRegister, RESTORE_REGISTER, GateFlags::NONE_FLAG, 0, 0, 1)

View File

@ -58,6 +58,13 @@ void NTypeBytecodeLowering::Lower(GateRef gate)
case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
LowerNTypedCreateArrayWithBuffer(gate);
break;
case EcmaOpcode::COPYRESTARGS_IMM8:
case EcmaOpcode::WIDE_COPYRESTARGS_PREF_IMM16:
LowerNTypedCopyRestArgs(gate);
break;
case EcmaOpcode::GETUNMAPPEDARGS:
LowerNTypedGetUnmappedArgs(gate);
break;
case EcmaOpcode::STOWNBYINDEX_IMM8_V8_IMM16:
case EcmaOpcode::STOWNBYINDEX_IMM16_V8_IMM16:
case EcmaOpcode::WIDE_STOWNBYINDEX_PREF_V8_IMM32:
@ -184,6 +191,28 @@ void NTypeBytecodeLowering::LowerNTypedCreateArrayWithBuffer(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
}
void NTypeBytecodeLowering::LowerNTypedCopyRestArgs(GateRef gate)
{
ASSERT(acc_.GetNumValueIn(gate) == 1);
GateRef restIdx = acc_.GetValueIn(gate, 0);
AddProfiling(gate);
ElementsKind kind = acc_.TryGetElementsKind(gate);
GateRef arguments =
builder_.CreateArguments(kind, CreateArgumentsAccessor::Mode::REST_ARGUMENTS, restIdx);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), arguments);
}
void NTypeBytecodeLowering::LowerNTypedGetUnmappedArgs(GateRef gate)
{
ASSERT(acc_.GetNumValueIn(gate) == 0);
GateRef restIdx = builder_.Int32(0);
AddProfiling(gate);
ElementsKind kind = acc_.TryGetElementsKind(gate);
GateRef arguments =
builder_.CreateArguments(kind, CreateArgumentsAccessor::Mode::UNMAPPED_ARGUMENTS, restIdx);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), arguments);
}
void NTypeBytecodeLowering::LowerNTypedStownByIndex(GateRef gate)
{
// 3: number of value inputs

View File

@ -48,6 +48,8 @@ private:
void Lower(GateRef gate);
void LowerNTypedCreateEmptyArray(GateRef gate);
void LowerNTypedCreateArrayWithBuffer(GateRef gate);
void LowerNTypedCopyRestArgs(GateRef gate);
void LowerNTypedGetUnmappedArgs(GateRef gate);
void LowerNTypedStownByIndex(GateRef gate);
void LowerLdLexVar(GateRef gate);
void LowerStLexVar(GateRef gate);

View File

@ -13,6 +13,7 @@
* limitations under the License.
*/
#include "ecmascript/js_arguments.h"
#include "ecmascript/compiler/ntype_hcr_lowering.h"
#include "ecmascript/dfx/vmstat/opt_code_profiler.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
@ -30,6 +31,9 @@ GateRef NTypeHCRLowering::VisitGate(GateRef gate)
case OpCode::CREATE_ARRAY_WITH_BUFFER:
LowerCreateArrayWithBuffer(gate, glue);
break;
case OpCode::CREATE_ARGUMENTS:
LowerCreateArguments(gate, glue);
break;
case OpCode::STORE_MODULE_VAR:
LowerStoreModuleVar(gate, glue);
break;
@ -111,6 +115,36 @@ void NTypeHCRLowering::LowerCreateArrayWithBuffer(GateRef gate, GateRef glue)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), array);
}
void NTypeHCRLowering::LowerCreateArguments(GateRef gate, GateRef glue)
{
CreateArgumentsAccessor accessor = acc_.GetCreateArgumentsAccessor(gate);
CreateArgumentsAccessor::Mode mode = accessor.GetMode();
Environment env(gate, circuit_, &builder_);
ArgumentAccessor argAcc(circuit_);
GateRef frameState = GetFrameState(gate);
GateRef actualArgc = argAcc.GetFrameArgsIn(frameState, FrameArgIdx::ACTUAL_ARGC);
GateRef startIdx = acc_.GetValueIn(gate, 0);
switch (mode) {
case CreateArgumentsAccessor::Mode::REST_ARGUMENTS: {
GateRef newGate = builder_.CallStub(glue, gate, CommonStubCSigns::CopyRestArgs,
{ glue, startIdx, builder_.TruncInt64ToInt32(actualArgc) });
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), newGate);
break;
}
case CreateArgumentsAccessor::Mode::UNMAPPED_ARGUMENTS: {
GateRef newGate = builder_.CallStub(glue, gate, CommonStubCSigns::GetUnmapedArgs,
{ glue, builder_.TruncInt64ToInt32(actualArgc) });
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), newGate);
break;
}
default: {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
}
}
GateRef NTypeHCRLowering::LoadFromConstPool(GateRef jsFunc, size_t index, size_t valVecType)
{
GateRef constPool = builder_.GetConstPool(jsFunc);

View File

@ -47,6 +47,7 @@ private:
void Lower(GateRef gate);
void LowerCreateArray(GateRef gate, GateRef glue);
void LowerCreateArrayWithBuffer(GateRef gate, GateRef glue);
void LowerCreateArguments(GateRef gate, GateRef glue);
void LowerCreateEmptyArray(GateRef gate);
void LowerCreateArrayWithOwn(GateRef gate, GateRef glue);
void LowerStoreModuleVar(GateRef gate, GateRef glue);

View File

@ -157,6 +157,7 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
case OpCode::STRING_FROM_SINGLE_CHAR_CODE:
case OpCode::ORDINARY_HAS_INSTANCE:
case OpCode::ECMA_STRING_CHECK:
case OpCode::CREATE_ARGUMENTS:
return VisitOthers(gate);
default:
return Circuit::NullGate();

View File

@ -610,6 +610,35 @@ private:
uint64_t bitField_;
};
class CreateArgumentsAccessor {
public:
enum Mode : uint8_t {
REST_ARGUMENTS,
UNMAPPED_ARGUMENTS,
INVALID,
};
static constexpr int BITS_SIZE = 8;
explicit CreateArgumentsAccessor(uint64_t value) : bitField_(value) {}
explicit CreateArgumentsAccessor(ElementsKind kind, Mode mode)
{
bitField_ = ElementsKindBits::Encode(kind) | ModeBits::Encode(mode);
}
Mode GetMode() const
{
return ModeBits::Get(bitField_);
}
uint64_t ToValue() const
{
return bitField_;
}
private:
using ElementsKindBits = panda::BitField<ElementsKind, 0, BITS_SIZE>;
using ModeBits = ElementsKindBits::NextField<Mode, BITS_SIZE>;
uint64_t bitField_;
};
class ObjectTypeAccessor {
public:
static constexpr int TYPE_BITS_SIZE = 32;

View File

@ -108,7 +108,8 @@ void OptCodeProfiler::FilterMethodToPrint()
void OptCodeProfiler::PrintMethodRecord(Key key, std::string methodName)
{
LOG_ECMA(INFO) << "==== methodId: " << key.GetMehodId() << ", methodName: " << methodName.c_str()
LOG_ECMA(INFO) << "==== methodId: " << key.GetMethodId()
<< ", methodName: " << methodName.c_str()
<< ", abcName: " << abcNames_[key.GetAbcId()] << " ====";
static constexpr int nameRightAdjustment = 46;

View File

@ -98,7 +98,7 @@ public:
return (uint32_t) (abcAndMethodId_ >> 32); // 32: 32bit
}
uint32_t GetMehodId() const
uint32_t GetMethodId() const
{
return (uint32_t) abcAndMethodId_;
}

View File

@ -0,0 +1,18 @@
# Copyright (c) 2024 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_aot_test_action("arguments") {
deps = []
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2024 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.
*/
class A {
constructor(a, b, ...args){
print("A: " + args);
}
}
class B extends A {
constructor() {
super(...arguments);
print(...arguments);
}
}
new B(1, 2, 3, 4, 5);
function func(a, b, ...args) {
print(args);
}
func(1);
func(1, 2);
func(1, 2, 3);
func(1, 2, 3, 4, 5);

View File

@ -0,0 +1,19 @@
# Copyright (c) 2024 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.
A: 3,4,5
1 2 3 4 5
3
3,4,5