mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 10:09:54 +00:00
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:
parent
93b3b5faa0
commit
1409ae1994
@ -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
|
||||
|
@ -376,6 +376,7 @@ private:
|
||||
V(TryStoreICByValue) \
|
||||
V(SetValueWithBarrier) \
|
||||
V(NewLexicalEnv) \
|
||||
V(CopyRestArgs) \
|
||||
V(GetUnmapedArgs) \
|
||||
V(NewThisObjectChecked) \
|
||||
V(ConstructorCheck) \
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -77,6 +77,7 @@ namespace panda::ecmascript::kungfu {
|
||||
V(TryStoreICByValue) \
|
||||
V(SetValueWithBarrier) \
|
||||
V(NewLexicalEnv) \
|
||||
V(CopyRestArgs) \
|
||||
V(GetUnmapedArgs) \
|
||||
V(NewThisObjectChecked) \
|
||||
V(ConstructorCheck) \
|
||||
|
@ -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 ||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -98,7 +98,7 @@ public:
|
||||
return (uint32_t) (abcAndMethodId_ >> 32); // 32: 32bit
|
||||
}
|
||||
|
||||
uint32_t GetMehodId() const
|
||||
uint32_t GetMethodId() const
|
||||
{
|
||||
return (uint32_t) abcAndMethodId_;
|
||||
}
|
||||
|
18
test/aottest/arguments/BUILD.gn
Normal file
18
test/aottest/arguments/BUILD.gn
Normal 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 = []
|
||||
}
|
36
test/aottest/arguments/arguments.ts
Normal file
36
test/aottest/arguments/arguments.ts
Normal 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);
|
19
test/aottest/arguments/expect_output.txt
Normal file
19
test/aottest/arguments/expect_output.txt
Normal 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
|
Loading…
Reference in New Issue
Block a user