mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-27 12:10:47 +00:00
AOT Builtin Math Function Lowering
1 On current AOT Builtin Math is called by c++ runtime trampoline, which is not an efficient solution. thus we call target math function directly. 2 CallNGCRuntime save bc offset When Aot call cc fucntion issue: https://gitee.com/open_harmony/dashboard?issue_id=I5Z281 Change-Id: I6ebf5b42d8b688c3f4dc886865f876d1b44a10a4
This commit is contained in:
commit
db10160072
2
BUILD.gn
2
BUILD.gn
@ -465,7 +465,7 @@ ecma_source = [
|
||||
"ecmascript/dfx/vmstat/runtime_stat.cpp",
|
||||
"ecmascript/dfx/vm_thread_control.cpp",
|
||||
"ecmascript/dump.cpp",
|
||||
"ecmascript/Relocator.cpp",
|
||||
"ecmascript/relocator.cpp",
|
||||
"ecmascript/ecma_string.cpp",
|
||||
"ecmascript/ecma_string_table.cpp",
|
||||
"ecmascript/ecma_vm.cpp",
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "ecmascript/compiler/bc_call_signature.h"
|
||||
#include "ecmascript/compiler/common_stubs.h"
|
||||
#include "ecmascript/deoptimizer.h"
|
||||
#include "ecmascript/Relocator.h"
|
||||
#include "ecmascript/relocator.h"
|
||||
#include "ecmascript/llvm_stackmap_parser.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/message_string.h"
|
||||
|
@ -1503,17 +1503,17 @@ void Builtins::InitializeMath(const JSHandle<GlobalEnv> &env, const JSHandle<JST
|
||||
JSHandle<JSHClass> mathClass = factory_->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, objFuncPrototypeVal);
|
||||
JSHandle<JSObject> mathObject = factory_->NewJSObjectWithInit(mathClass);
|
||||
SetFunction(env, mathObject, "abs", Math::Abs, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "acos", Math::Acos, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "acos", Math::Acos, FunctionLength::ONE, static_cast<uint8_t>(BUILTINS_STUB_ID(ACOS)));
|
||||
SetFunction(env, mathObject, "acosh", Math::Acosh, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "asin", Math::Asin, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "asinh", Math::Asinh, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "atan", Math::Atan, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "atan", Math::Atan, FunctionLength::ONE, static_cast<uint8_t>(BUILTINS_STUB_ID(ATAN)));
|
||||
SetFunction(env, mathObject, "atanh", Math::Atanh, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "atan2", Math::Atan2, FunctionLength::TWO);
|
||||
SetFunction(env, mathObject, "cbrt", Math::Cbrt, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "ceil", Math::Ceil, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "clz32", Math::Clz32, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "cos", Math::Cos, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "cos", Math::Cos, FunctionLength::ONE, static_cast<uint8_t>(BUILTINS_STUB_ID(COS)));
|
||||
SetFunction(env, mathObject, "cosh", Math::Cosh, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "exp", Math::Exp, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "expm1", Math::Expm1, FunctionLength::ONE);
|
||||
@ -1531,9 +1531,9 @@ void Builtins::InitializeMath(const JSHandle<GlobalEnv> &env, const JSHandle<JST
|
||||
SetFunction(env, mathObject, "random", Math::Random, FunctionLength::ZERO);
|
||||
SetFunction(env, mathObject, "round", Math::Round, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "sign", Math::Sign, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "sin", Math::Sin, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "sin", Math::Sin, FunctionLength::ONE, static_cast<uint8_t>(BUILTINS_STUB_ID(SIN)));
|
||||
SetFunction(env, mathObject, "sinh", Math::Sinh, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "sqrt", Math::Sqrt, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "sqrt", Math::Sqrt, FunctionLength::ONE, static_cast<uint8_t>(BUILTINS_STUB_ID(SQRT)));
|
||||
SetFunction(env, mathObject, "tan", Math::Tan, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "tanh", Math::Tanh, FunctionLength::ONE);
|
||||
SetFunction(env, mathObject, "trunc", Math::Trunc, FunctionLength::ONE);
|
||||
|
@ -48,6 +48,7 @@ source_set("libark_jsoptimizer_set") {
|
||||
"builtins/builtins_string_stub_builder.cpp",
|
||||
"builtins/builtins_stubs.cpp",
|
||||
"builtins/containers_stub_builder.cpp",
|
||||
"builtins_lowering.cpp",
|
||||
"bytecode_circuit_builder.cpp",
|
||||
"bytecode_info_collector.cpp",
|
||||
"bytecodes.cpp",
|
||||
|
@ -34,14 +34,15 @@ void BuiltinsStubCSigns::Initialize()
|
||||
static_cast<Environment*>(env))); \
|
||||
});
|
||||
|
||||
BUILTINS_STUB_LIST(INIT_SIGNATURES)
|
||||
ASM_INTERPRETER_BUILTINS_STUB_LIST(INIT_SIGNATURES)
|
||||
#undef INIT_SIGNATURES
|
||||
BuiltinsCallSignature::Initialize(&builtinsCSign_);
|
||||
}
|
||||
|
||||
void BuiltinsStubCSigns::GetCSigns(std::vector<const CallSignature*>& outCSigns)
|
||||
{
|
||||
for (size_t i = 0; i < NUM_OF_BUILTINS_STUBS; i++) {
|
||||
const size_t firstStubId = BUILTINS_STUB_ID(NONE) + 1;
|
||||
for (size_t i = firstStubId; i < NUM_OF_BUILTINS_STUBS; i++) {
|
||||
outCSigns.push_back(&callSigns_[i]);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,11 @@
|
||||
#include "ecmascript/compiler/rt_call_signature.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
#define BUILTINS_STUB_LIST(V) \
|
||||
|
||||
#define PADDING_STUB_LIST(V) \
|
||||
V(NONE)
|
||||
|
||||
#define ASM_INTERPRETER_BUILTINS_STUB_LIST(V) \
|
||||
V(CharCodeAt) \
|
||||
V(IndexOf) \
|
||||
V(Substring) \
|
||||
@ -40,13 +44,24 @@ namespace panda::ecmascript::kungfu {
|
||||
V(ArrayListForEach) \
|
||||
V(ArrayListReplaceAllElements) \
|
||||
|
||||
#define AOT_BUILTINS_STUB_LIST(V) \
|
||||
V(SQRT) \
|
||||
V(COS) \
|
||||
V(SIN) \
|
||||
V(ACOS) \
|
||||
V(ATAN) \
|
||||
|
||||
class BuiltinsStubCSigns {
|
||||
public:
|
||||
enum ID {
|
||||
#define DEF_STUB_ID(name) name,
|
||||
BUILTINS_STUB_LIST(DEF_STUB_ID)
|
||||
PADDING_STUB_LIST(DEF_STUB_ID)
|
||||
ASM_INTERPRETER_BUILTINS_STUB_LIST(DEF_STUB_ID)
|
||||
#undef DEF_STUB_ID
|
||||
NUM_OF_BUILTINS_STUBS,
|
||||
#define DEF_STUB_ID(name) name,
|
||||
AOT_BUILTINS_STUB_LIST(DEF_STUB_ID)
|
||||
#undef DEF_STUB_ID
|
||||
NUM_OF_BUILTINS_STUBS
|
||||
};
|
||||
|
||||
static void Initialize();
|
||||
@ -63,6 +78,11 @@ public:
|
||||
{
|
||||
return &builtinsCSign_;
|
||||
}
|
||||
|
||||
static bool IsFastBuiltin(ID builtinId)
|
||||
{
|
||||
return builtinId > NONE && builtinId < NUM_OF_BUILTINS_STUBS;
|
||||
}
|
||||
private:
|
||||
static CallSignature callSigns_[NUM_OF_BUILTINS_STUBS];
|
||||
static CallSignature builtinsCSign_;
|
||||
|
@ -96,7 +96,7 @@ public:
|
||||
void GenerateCircuitImpl(GateRef glue, GateRef nativeCode, GateRef func, GateRef thisValue, \
|
||||
GateRef numArgs); \
|
||||
};
|
||||
BUILTINS_STUB_LIST(DECLARE_BUILTINS_STUB_CLASS)
|
||||
ASM_INTERPRETER_BUILTINS_STUB_LIST(DECLARE_BUILTINS_STUB_CLASS)
|
||||
#undef DECLARE_BUILTINS_STUB_CLASS
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTINS_STUB_H
|
||||
|
284
ecmascript/compiler/builtins_lowering.cpp
Normal file
284
ecmascript/compiler/builtins_lowering.cpp
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/builtins_lowering.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void BuiltinLowering::LowerTypedCallBuitin(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
auto bitfield = acc_.GetBitField(gate);
|
||||
auto idGate = acc_.GetValueIn(gate, bitfield - 1);
|
||||
auto id = static_cast<BuiltinsStubCSigns::ID>(acc_.GetBitField(idGate));
|
||||
switch (id) {
|
||||
case BUILTINS_STUB_ID(SQRT):
|
||||
LowerTypedSqrt(gate);
|
||||
break;
|
||||
case BUILTINS_STUB_ID(COS):
|
||||
case BUILTINS_STUB_ID(SIN):
|
||||
case BUILTINS_STUB_ID(ACOS):
|
||||
case BUILTINS_STUB_ID(ATAN):
|
||||
LowerTypedTrigonometric(gate, id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltinLowering::LowerTypedTrigonometric(GateRef gate, BuiltinsStubCSigns::ID id)
|
||||
{
|
||||
auto ret = TypeTrigonometric(gate, id);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
|
||||
}
|
||||
|
||||
GateRef BuiltinLowering::TypeTrigonometric(GateRef gate, BuiltinsStubCSigns::ID id)
|
||||
{
|
||||
auto env = builder_.GetCurrentEnvironment();
|
||||
Label entry(&builder_);
|
||||
env->SubCfgEntry(&entry);
|
||||
|
||||
Label numberBranch(&builder_);
|
||||
Label notNumberBranch(&builder_);
|
||||
Label exit(&builder_);
|
||||
|
||||
GateRef a0 = acc_.GetValueIn(gate, 0);
|
||||
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
|
||||
|
||||
builder_.Branch(builder_.TaggedIsNumber(a0), &numberBranch, ¬NumberBranch);
|
||||
builder_.Bind(&numberBranch);
|
||||
{
|
||||
Label IsInt(&builder_);
|
||||
Label NotInt(&builder_);
|
||||
Label calc(&builder_);
|
||||
DEFVAlUE(value, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
|
||||
builder_.Branch(builder_.TaggedIsInt(a0), &IsInt, &NotInt);
|
||||
builder_.Bind(&IsInt);
|
||||
{
|
||||
value = builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(a0));
|
||||
builder_.Jump(&calc);
|
||||
}
|
||||
builder_.Bind(&NotInt);
|
||||
{
|
||||
value = builder_.GetDoubleOfTDouble(a0);
|
||||
builder_.Jump(&calc);
|
||||
}
|
||||
builder_.Bind(&calc);
|
||||
{
|
||||
Label IsNan(&builder_);
|
||||
Label NotNan(&builder_);
|
||||
GateRef condition = builder_.DoubleIsNAN(*value);
|
||||
builder_.Branch(condition, &IsNan, &NotNan);
|
||||
builder_.Bind(&NotNan);
|
||||
{
|
||||
ArgumentAccessor argAcc_(circuit_);
|
||||
auto glue = argAcc_.GetCommonArgGate(CommonArgIdx::GLUE);
|
||||
int index = RTSTUB_ID(FloatCos);
|
||||
switch (id) {
|
||||
case BUILTINS_STUB_ID(ACOS):
|
||||
index = RTSTUB_ID(FloatACos);
|
||||
break;
|
||||
case BUILTINS_STUB_ID(ATAN):
|
||||
index = RTSTUB_ID(FloatATan);
|
||||
break;
|
||||
case BUILTINS_STUB_ID(COS):
|
||||
index = RTSTUB_ID(FloatCos);
|
||||
break;
|
||||
case BUILTINS_STUB_ID(SIN):
|
||||
index = RTSTUB_ID(FloatSin);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
result = builder_.CallNGCRuntime(glue, index, Gate::InvalidGateRef, {*value});
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(&IsNan);
|
||||
{
|
||||
result = builder_.DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
builder_.Bind(¬NumberBranch);
|
||||
{
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
|
||||
builder_.Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BuiltinLowering::LowerTypedSqrt(GateRef gate)
|
||||
{
|
||||
auto ret = TypedSqrt(gate);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
|
||||
}
|
||||
|
||||
GateRef BuiltinLowering::TypedSqrt(GateRef gate)
|
||||
{
|
||||
auto env = builder_.GetCurrentEnvironment();
|
||||
Label entry(&builder_);
|
||||
env->SubCfgEntry(&entry);
|
||||
|
||||
Label numberBranch(&builder_);
|
||||
Label notNumberBranch(&builder_);
|
||||
Label exit(&builder_);
|
||||
GateRef a0 = acc_.GetValueIn(gate, 0);
|
||||
DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant());
|
||||
|
||||
builder_.Branch(builder_.TaggedIsNumber(a0), &numberBranch, ¬NumberBranch);
|
||||
builder_.Bind(&numberBranch);
|
||||
{
|
||||
Label IsInt(&builder_);
|
||||
Label NotInt(&builder_);
|
||||
Label calc(&builder_);
|
||||
DEFVAlUE(value, (&builder_), VariableType::FLOAT64(), builder_.Double(0));
|
||||
builder_.Branch(builder_.TaggedIsInt(a0), &IsInt, &NotInt);
|
||||
builder_.Bind(&IsInt);
|
||||
{
|
||||
value = builder_.ChangeInt32ToFloat64(builder_.GetInt32OfTInt(a0));
|
||||
builder_.Jump(&calc);
|
||||
}
|
||||
builder_.Bind(&NotInt);
|
||||
{
|
||||
value = builder_.GetDoubleOfTDouble(a0);
|
||||
builder_.Jump(&calc);
|
||||
}
|
||||
builder_.Bind(&calc);
|
||||
{
|
||||
Label signbit(&builder_);
|
||||
Label notSignbit(&builder_);
|
||||
GateRef negativeInfinity = builder_.Double(-base::POSITIVE_INFINITY);
|
||||
GateRef isNegativeInfinity = builder_.Equal(*value, negativeInfinity);
|
||||
isNegativeInfinity = builder_.Equal(builder_.SExtInt1ToInt32(isNegativeInfinity), builder_.Int32(1));
|
||||
GateRef negativeNan = builder_.Double(-base::NAN_VALUE);
|
||||
GateRef isNegativeNan = builder_.Equal(*value, negativeNan);
|
||||
isNegativeNan = builder_.Equal(builder_.SExtInt1ToInt32(isNegativeNan), builder_.Int32(1));
|
||||
GateRef negativeZero = builder_.Double(-0.0);
|
||||
GateRef isNegativeZero = builder_.Equal(*value, negativeZero);
|
||||
// If value is negative, include -NaN and -Infinity but not -0.0, the result is NaN
|
||||
GateRef negNanOrInfinityNotZero = builder_.BoolOr(isNegativeNan, isNegativeInfinity);
|
||||
negNanOrInfinityNotZero = builder_.BoolAnd(negNanOrInfinityNotZero, builder_.BoolNot(isNegativeZero));
|
||||
builder_.Branch(negNanOrInfinityNotZero, &signbit, ¬Signbit);
|
||||
builder_.Bind(&signbit);
|
||||
{
|
||||
result = builder_.DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(¬Signbit);
|
||||
{
|
||||
Label naN(&builder_);
|
||||
Label notNan(&builder_);
|
||||
GateRef condition = builder_.DoubleIsNAN(*value);
|
||||
builder_.Branch(condition, &naN, ¬Nan);
|
||||
builder_.Bind(¬Nan);
|
||||
{
|
||||
ArgumentAccessor argAcc_(circuit_);
|
||||
auto glue = argAcc_.GetCommonArgGate(CommonArgIdx::GLUE);
|
||||
result = builder_.CallNGCRuntime(
|
||||
glue, RTSTUB_ID(FloatSqrt), Gate::InvalidGateRef, {*value});
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
// If value is NaN, the result is NaN
|
||||
builder_.Bind(&naN);
|
||||
{
|
||||
result = builder_.DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
builder_.Bind(¬NumberBranch);
|
||||
{
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
|
||||
builder_.Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BuiltinLowering::LowerCallTargetCheck(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef function = acc_.GetValueIn(gate, 0); // 0: function
|
||||
GateRef id = acc_.GetValueIn(gate, 1); // 1: buitin id
|
||||
Label isHeapObject(&builder_);
|
||||
Label notHeapObject(&builder_);
|
||||
Label funcIsCallable(&builder_);
|
||||
Label exit(&builder_);
|
||||
GateRef isObject = builder_.TaggedIsHeapObject(function);
|
||||
DEFVAlUE(result, (&builder_), VariableType::BOOL(), builder_.False());
|
||||
builder_.Branch(isObject, &isHeapObject, ¬HeapObject);
|
||||
builder_.Bind(¬HeapObject);
|
||||
{
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
|
||||
builder_.Bind(&isHeapObject);
|
||||
{
|
||||
GateRef callable = builder_.IsCallable(function);
|
||||
builder_.Branch(callable, &funcIsCallable, &exit);
|
||||
builder_.Bind(&funcIsCallable);
|
||||
{
|
||||
GateRef method = builder_.Load(VariableType::JS_ANY(), function,
|
||||
builder_.IntPtr(JSFunctionBase::METHOD_OFFSET));
|
||||
GateRef builtinId = builder_.GetCallBuiltinId(method);
|
||||
result = builder_.Int64Equal(builtinId, id);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
|
||||
}
|
||||
|
||||
BuiltinsStubCSigns::ID BuiltinLowering::GetBuiltinId(std::string idStr)
|
||||
{
|
||||
const std::map<std::string, BuiltinsStubCSigns::ID> str2BuiltinId = {
|
||||
{"sqrt", BUILTINS_STUB_ID(SQRT)},
|
||||
{"cos", BUILTINS_STUB_ID(COS)},
|
||||
{"sin", BUILTINS_STUB_ID(SIN)},
|
||||
{"acos", BUILTINS_STUB_ID(ACOS)},
|
||||
{"atan", BUILTINS_STUB_ID(ATAN)},
|
||||
};
|
||||
if (str2BuiltinId.count(idStr) > 0) {
|
||||
return str2BuiltinId.at(idStr);
|
||||
}
|
||||
return BUILTINS_STUB_ID(NONE);
|
||||
}
|
||||
|
||||
GateRef BuiltinLowering::CheckPara(GateRef gate, BuiltinsStubCSigns::ID id)
|
||||
{
|
||||
GateRef a0 = acc_.GetValueIn(gate, 1);
|
||||
GateRef paracheck = builder_.TaggedIsNumber(a0);
|
||||
switch (id) {
|
||||
case BuiltinsStubCSigns::ID::SQRT:
|
||||
case BuiltinsStubCSigns::ID::COS:
|
||||
case BuiltinsStubCSigns::ID::SIN:
|
||||
case BuiltinsStubCSigns::ID::ACOS:
|
||||
case BuiltinsStubCSigns::ID::ATAN: {
|
||||
paracheck = builder_.TaggedIsNumber(a0);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
return paracheck;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
45
ecmascript/compiler/builtins_lowering.h
Normal file
45
ecmascript/compiler/builtins_lowering.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_BUILTIN_LOWERING_LOWERING_H
|
||||
#define ECMASCRIPT_COMPILER_BUILTIN_LOWERING_LOWERING_H
|
||||
|
||||
#include <string>
|
||||
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
|
||||
#include "ecmascript/compiler/argument_accessor.h"
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
class BuiltinLowering {
|
||||
public:
|
||||
BuiltinLowering(Circuit *circuit): circuit_(circuit), builder_(circuit),
|
||||
acc_(circuit) {}
|
||||
~BuiltinLowering() = default;
|
||||
void LowerTypedCallBuitin(GateRef gate);
|
||||
void LowerCallTargetCheck(GateRef gate);
|
||||
static BuiltinsStubCSigns::ID GetBuiltinId(std::string idStr);
|
||||
GateRef CheckPara(GateRef gate, BuiltinsStubCSigns::ID id);
|
||||
private:
|
||||
void LowerTypedTrigonometric(GateRef gate, BuiltinsStubCSigns::ID id);
|
||||
GateRef TypeTrigonometric(GateRef gate, BuiltinsStubCSigns::ID id);
|
||||
void LowerTypedSqrt(GateRef gate);
|
||||
GateRef TypedSqrt(GateRef gate);
|
||||
|
||||
Circuit *circuit_ {nullptr};
|
||||
CircuitBuilder builder_;
|
||||
GateAccessor acc_;
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BUILTIN_LOWERING_LOWERING_H
|
@ -90,6 +90,7 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
|
||||
case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8:
|
||||
case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
|
||||
case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
|
||||
case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
|
||||
flags |= BytecodeFlags::SUPPORT_DEOPT;
|
||||
break;
|
||||
case EcmaOpcode::RETURNUNDEFINED:
|
||||
|
@ -1149,21 +1149,6 @@ DEF_CALL_SIGNATURE(InsertOldToNewRSet)
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(AotFloatMod)
|
||||
{
|
||||
// 2 : 2 input parameters
|
||||
CallSignature index("AotFloatMod", 0, 2, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = index;
|
||||
// 2 : 2 input parameters
|
||||
std::array<VariableType, 2> params = {
|
||||
VariableType::FLOAT64(),
|
||||
VariableType::FLOAT64(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(false);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(FloatMod)
|
||||
{
|
||||
// 2 : 2 input parameters
|
||||
@ -1179,6 +1164,76 @@ DEF_CALL_SIGNATURE(FloatMod)
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(FloatSqrt)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
CallSignature index("FloatSqrt", 0, 1, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = index;
|
||||
// 1 : 1 input parameters
|
||||
std::array<VariableType, 1> params = {
|
||||
VariableType::FLOAT64(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(FloatCos)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
CallSignature index("FloatCos", 0, 1, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = index;
|
||||
// 1 : 1 input parameters
|
||||
std::array<VariableType, 1> params = {
|
||||
VariableType::FLOAT64(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(FloatSin)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
CallSignature index("FloatSin", 0, 1, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = index;
|
||||
// 1 : 1 input parameters
|
||||
std::array<VariableType, 1> params = {
|
||||
VariableType::FLOAT64(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(FloatACos)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
CallSignature index("FloatACos", 0, 1, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = index;
|
||||
// 1 : 1 input parameters
|
||||
std::array<VariableType, 1> params = {
|
||||
VariableType::FLOAT64(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(FloatATan)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
CallSignature index("FloatATan", 0, 1, ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = index;
|
||||
// 1 : 1 input parameters
|
||||
std::array<VariableType, 1> params = {
|
||||
VariableType::FLOAT64(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(FindElementWithCache)
|
||||
{
|
||||
// 4 : 4 input parameters
|
||||
|
@ -369,8 +369,12 @@ private:
|
||||
V(FatalPrint) \
|
||||
V(InsertOldToNewRSet) \
|
||||
V(DoubleToInt) \
|
||||
V(AotFloatMod) \
|
||||
V(FloatMod) \
|
||||
V(FloatSqrt) \
|
||||
V(FloatCos) \
|
||||
V(FloatSin) \
|
||||
V(FloatACos) \
|
||||
V(FloatATan) \
|
||||
V(FindElementWithCache) \
|
||||
V(MarkingBarrier) \
|
||||
V(StoreBarrier) \
|
||||
|
@ -877,6 +877,18 @@ inline GateRef CircuitBuilder::IsBase(GateRef ctor)
|
||||
return Int32LessThanOrEqual(kind, Int32(static_cast<int32_t>(FunctionKind::CLASS_CONSTRUCTOR)));
|
||||
}
|
||||
|
||||
inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef x, BuiltinsStubCSigns::ID id)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
GateRef idGate = Int8(static_cast<int8_t>(id));
|
||||
auto numberMathOp = TypedCallOperator(MachineType::I64, currentControl, currentDepend, {x, idGate});
|
||||
currentLabel->SetControl(numberMathOp);
|
||||
currentLabel->SetDepend(numberMathOp);
|
||||
return numberMathOp;
|
||||
}
|
||||
|
||||
void Label::Seal()
|
||||
{
|
||||
return impl_->Seal();
|
||||
|
@ -172,6 +172,23 @@ GateRef CircuitBuilder::TypeCheck(GateType type, GateRef gate)
|
||||
{gate}, GateType::NJSValue());
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::CallTargetCheck(GateRef function, GateRef id)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto state = currentLabel->GetControl();
|
||||
auto depend = currentLabel->GetDepend();
|
||||
std::vector<GateRef> inLists;
|
||||
inLists.emplace_back(state);
|
||||
inLists.emplace_back(depend);
|
||||
inLists.emplace_back(function);
|
||||
inLists.emplace_back(id);
|
||||
GateRef ret = GetCircuit()->NewGate(OpCode(OpCode::TYPED_CALL_CHECK), inLists.size() - 2, // 2: state&depend
|
||||
inLists, GateType::NJSValue());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetLexicalEnv(GateRef depend)
|
||||
{
|
||||
return GetCircuit()->NewGate(OpCode(OpCode::GET_ENV), MachineType::I64, 0, {depend}, GateType::TaggedValue());
|
||||
@ -189,6 +206,14 @@ GateRef CircuitBuilder::TypedBinaryOperator(MachineType type, TypedBinOp binOp,
|
||||
return GetCircuit()->NewGate(OpCode(OpCode::TYPED_BINARY_OP), type, operandTypes, inList, gateType);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TypedCallOperator(MachineType type, GateRef state, GateRef depend, std::vector<GateRef> inList)
|
||||
{
|
||||
BitField number = static_cast<BitField>(inList.size());
|
||||
inList.insert(inList.begin(), depend);
|
||||
inList.insert(inList.begin(), state);
|
||||
return GetCircuit()->NewGate(OpCode(OpCode::TYPED_CALL), type, number, inList, GateType::AnyType());
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::TypeConvert(MachineType type, GateType typeFrom, GateType typeTo,
|
||||
const std::vector<GateRef>& inList)
|
||||
{
|
||||
@ -756,6 +781,15 @@ GateRef CircuitBuilder::GetGlobalConstantValue(VariableType type, GateRef glue,
|
||||
return Load(type, gConstAddr, constantIndex);
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::GetCallBuiltinId(GateRef method)
|
||||
{
|
||||
GateRef extraLiteralInfoOffset = IntPtr(Method::EXTRA_LITERAL_INFO_OFFSET);
|
||||
GateRef extraLiteralInfo = Load(VariableType::INT64(), method, extraLiteralInfoOffset);
|
||||
return Int64And(
|
||||
Int64LSR(extraLiteralInfo, Int64(MethodLiteral::BuiltinIdBits::START_BIT)),
|
||||
Int64((1LU << MethodLiteral::BuiltinIdBits::SIZE) - 1));
|
||||
}
|
||||
|
||||
Environment::Environment(size_t arguments, CircuitBuilder *builder)
|
||||
: circuit_(builder->GetCircuit()), circuitBuilder_(builder), arguments_(arguments)
|
||||
{
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
|
||||
|
||||
#include "ecmascript/base/number_helper.h"
|
||||
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/call_signature.h"
|
||||
#include "ecmascript/compiler/gate.h"
|
||||
@ -210,8 +211,11 @@ public:
|
||||
// low level interface
|
||||
GateRef ObjectTypeCheck(GateType type, GateRef gate, GateRef hclassOffset);
|
||||
GateRef TypeCheck(GateType type, GateRef gate);
|
||||
GateRef CallTargetCheck(GateRef function, GateRef id);
|
||||
GateRef TypedBinaryOperator(MachineType type, TypedBinOp binOp, GateType typeLeft, GateType typeRight,
|
||||
std::vector<GateRef> inList, GateType gateType);
|
||||
GateRef TypedCallOperator(MachineType type, GateRef state, GateRef depend, std::vector<GateRef> inList);
|
||||
inline GateRef TypedCallBuiltin(GateRef x, BuiltinsStubCSigns::ID id);
|
||||
GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList);
|
||||
GateRef TypedUnaryOperator(MachineType type, TypedUnOp unaryOp, GateType typeVal,
|
||||
const std::vector<GateRef>& inList, GateType gateType);
|
||||
@ -255,6 +259,7 @@ public:
|
||||
GateRef BinaryLogic(OpCode opcode, GateRef left, GateRef right);
|
||||
GateRef BinaryCmp(OpCode opcode, GateRef left, GateRef right, BitField condition);
|
||||
static MachineType GetMachineTypeFromVariableType(VariableType type);
|
||||
GateRef GetCallBuiltinId(GateRef method);
|
||||
Circuit *GetCircuit() const
|
||||
{
|
||||
return circuit_;
|
||||
|
@ -282,11 +282,21 @@ const Properties& OpCode::GetProperties() const
|
||||
static const Properties ps { I1, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT };
|
||||
return ps;
|
||||
}
|
||||
// ts type lowering relate IR
|
||||
case TYPED_CALL_CHECK: {
|
||||
static const Properties ps { I1, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, MANY_VALUE(ANYVALUE), NO_ROOT };
|
||||
return ps;
|
||||
}
|
||||
case TYPED_BINARY_OP: {
|
||||
static const Properties ps { FLEX, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND,
|
||||
VALUE(ANYVALUE, ANYVALUE, I8), NO_ROOT };
|
||||
return ps;
|
||||
}
|
||||
case TYPED_CALL: {
|
||||
static const Properties ps { FLEX, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND,
|
||||
MANY_VALUE(ANYVALUE), NO_ROOT };
|
||||
return ps;
|
||||
}
|
||||
case TYPE_CONVERT: {
|
||||
static const Properties ps { FLEX, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, VALUE(ANYVALUE), NO_ROOT };
|
||||
return ps;
|
||||
@ -438,7 +448,9 @@ std::string OpCode::Str() const
|
||||
{SAVE_REGISTER, "SAVE_REGISTER"},
|
||||
{OBJECT_TYPE_CHECK, "OBJECT_TYPE_CHECK"},
|
||||
{TYPE_CHECK, "TYPE_CHECK"},
|
||||
{TYPED_CALL_CHECK, "TYPED_CALL_CHECK"},
|
||||
{TYPED_BINARY_OP, "TYPED_BINARY_OP"},
|
||||
{TYPED_CALL, "TYPED_CALL"},
|
||||
{TYPE_CONVERT, "TYPE_CONVERT"},
|
||||
{TYPED_UNARY_OP, "TYPED_UNARY_OP"},
|
||||
{TO_LENGTH, "TO_LENGTH"},
|
||||
@ -1402,7 +1414,8 @@ bool OpCode::IsGeneralState() const
|
||||
(op_ == OpCode::TYPED_BINARY_OP) || (op_ == OpCode::TYPE_CONVERT) || (op_ == OpCode::TYPED_UNARY_OP) ||
|
||||
(op_ == OpCode::TO_LENGTH) || (op_ == OpCode::HEAP_ALLOC) ||
|
||||
(op_ == OpCode::LOAD_ELEMENT) || (op_ == OpCode::LOAD_PROPERTY) ||
|
||||
(op_ == OpCode::STORE_ELEMENT) || (op_ == OpCode::STORE_PROPERTY));
|
||||
(op_ == OpCode::STORE_ELEMENT) || (op_ == OpCode::STORE_PROPERTY) ||
|
||||
(op_ == OpCode::TYPED_CALL));
|
||||
}
|
||||
|
||||
bool OpCode::IsTerminalState() const
|
||||
|
@ -221,7 +221,9 @@ public:
|
||||
SAVE_REGISTER,
|
||||
OBJECT_TYPE_CHECK,
|
||||
TYPE_CHECK,
|
||||
TYPED_CALL_CHECK,
|
||||
TYPED_BINARY_OP,
|
||||
TYPED_CALL,
|
||||
TYPE_CONVERT,
|
||||
TYPED_UNARY_OP,
|
||||
TO_LENGTH,
|
||||
|
@ -685,16 +685,10 @@ LLVMValueRef LLVMIRBuilder::GetBuiltinsStubOffset(LLVMValueRef glue)
|
||||
return LLVMConstInt(glueType, JSThread::GlueData::GetBuiltinsStubEntriesOffset(compCfg_->Is32Bit()), 0);
|
||||
}
|
||||
|
||||
// Only related to the call bytecode in Aot can record bcoffset
|
||||
bool LLVMIRBuilder::NeedBCOffset(OpCode op)
|
||||
{
|
||||
return callConv_ == CallSignature::CallConv::WebKitJSCallConv && op == OpCode::NOGC_RUNTIME_CALL;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset,
|
||||
const std::vector<GateRef> &inList, OpCode op)
|
||||
const std::vector<GateRef> &inList, CallExceptionKind kind)
|
||||
{
|
||||
if (NeedBCOffset(op)) {
|
||||
if (kind == CallExceptionKind::HAS_BC_OFFSET) {
|
||||
actualNumArgs = inList.size() - 1;
|
||||
bcOffset = gate2LValue_[inList[actualNumArgs]];
|
||||
} else {
|
||||
@ -702,6 +696,13 @@ void LLVMIRBuilder::ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueR
|
||||
}
|
||||
}
|
||||
|
||||
LLVMIRBuilder::CallExceptionKind LLVMIRBuilder::GetCallExceptionKind(size_t index, OpCode op) const
|
||||
{
|
||||
bool hasBcOffset = (callConv_ == CallSignature::CallConv::WebKitJSCallConv && op == OpCode::NOGC_RUNTIME_CALL &&
|
||||
index == RTSTUB_ID(JSCall));
|
||||
return hasBcOffset ? CallExceptionKind::HAS_BC_OFFSET : CallExceptionKind::NO_BC_OFFSET;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op)
|
||||
{
|
||||
size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
|
||||
@ -712,6 +713,7 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
LLVMValueRef rtoffset;
|
||||
LLVMValueRef rtbaseoffset;
|
||||
LLVMValueRef callee;
|
||||
CallExceptionKind kind = CallExceptionKind::NO_BC_OFFSET;
|
||||
if (op == OpCode::CALL) {
|
||||
calleeDescriptor = CommonStubCSigns::Get(index);
|
||||
rtoffset = GetCoStubOffset(glue, index);
|
||||
@ -722,6 +724,7 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
rtoffset = GetRTStubOffset(glue, index);
|
||||
rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
|
||||
callee = GetFunction(glue, calleeDescriptor, rtbaseoffset);
|
||||
kind = GetCallExceptionKind(index, op);
|
||||
} else {
|
||||
LLVMValueRef opcodeOffset = gate2LValue_[inList[targetIndex]];
|
||||
rtoffset = GetBuiltinsStubOffset(glue);
|
||||
@ -753,7 +756,7 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
}
|
||||
size_t actualNumArgs = 0;
|
||||
LLVMValueRef bcOffset = LLVMConstInt(LLVMInt32Type(), 0, 0);
|
||||
ComputeArgCountAndBCOffset(actualNumArgs, bcOffset, inList, op);
|
||||
ComputeArgCountAndBCOffset(actualNumArgs, bcOffset, inList, kind);
|
||||
|
||||
// then push the actual parameter for js function call
|
||||
for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) {
|
||||
@ -777,7 +780,7 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
LLVMValueRef call = nullptr;
|
||||
LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, calleeDescriptor);
|
||||
callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
|
||||
if (NeedBCOffset(op)) {
|
||||
if (kind == CallExceptionKind::HAS_BC_OFFSET) {
|
||||
std::vector<LLVMValueRef> values;
|
||||
auto bcIndex = LLVMConstInt(LLVMInt64Type(), static_cast<int>(SpecVregIndex::BC_OFFSET_INDEX), 1);
|
||||
values.push_back(bcIndex);
|
||||
|
@ -314,6 +314,10 @@ private:
|
||||
GLUE,
|
||||
FIRST_PARAMETER
|
||||
};
|
||||
enum class CallExceptionKind : bool {
|
||||
HAS_BC_OFFSET = true,
|
||||
NO_BC_OFFSET = false
|
||||
};
|
||||
LLVMRealPredicate ConvertLLVMPredicateFromFCMP(FCmpCondition cond);
|
||||
LLVMIntPredicate ConvertLLVMPredicateFromICMP(ICmpCondition cond);
|
||||
LLVMValueRef GetGlue(const std::vector<GateRef> &inList);
|
||||
@ -323,9 +327,9 @@ private:
|
||||
LLVMValueRef GetBCDebugStubOffset(LLVMValueRef glue);
|
||||
LLVMValueRef GetBuiltinsStubOffset(LLVMValueRef glue);
|
||||
LLVMValueRef GetBaseOffset(GateRef gate, LLVMValueRef glue);
|
||||
bool NeedBCOffset(OpCode op);
|
||||
CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const;
|
||||
void ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset, const std::vector<GateRef> &inList,
|
||||
OpCode op);
|
||||
CallExceptionKind kind);
|
||||
void SaveLexicalEnvOnFrame(LLVMValueRef value);
|
||||
LLVMTypeRef GetExperimentalDeoptTy();
|
||||
LLVMValueRef GetExperimentalDeopt(LLVMModuleRef &module);
|
||||
|
@ -3459,8 +3459,8 @@ void SlowPathLowering::LowerCallThisArg1(GateRef gate, GateRef glue)
|
||||
GateRef actualArgc = builder_.Int64(ComputeCallArgc(gate, EcmaOpcode::CALLTHIS1_IMM8_V8_V8));
|
||||
GateRef newTarget = builder_.Undefined();
|
||||
GateRef thisObj = acc_.GetValueIn(gate, 0);
|
||||
GateRef a0 = acc_.GetValueIn(gate, 1);
|
||||
GateRef func = acc_.GetValueIn(gate, 2);
|
||||
GateRef a0 = acc_.GetValueIn(gate, 1); // 1:first parameter
|
||||
GateRef func = acc_.GetValueIn(gate, 2); // 2:function
|
||||
GateRef bcOffset = builder_.Int64(acc_.GetBytecodeIndex(gate));
|
||||
GateRef env = builder_.Undefined();
|
||||
LowerToJSCall(gate, glue, {glue, env, actualArgc, func, newTarget, thisObj, a0, bcOffset});
|
||||
@ -3476,8 +3476,8 @@ void SlowPathLowering::LowerCallargs2Imm8V8V8(GateRef gate, GateRef glue)
|
||||
GateRef newTarget = builder_.Undefined();
|
||||
GateRef thisObj = builder_.Undefined();
|
||||
GateRef a0 = acc_.GetValueIn(gate, 0);
|
||||
GateRef a1 = acc_.GetValueIn(gate, 1);
|
||||
GateRef func = acc_.GetValueIn(gate, 2);
|
||||
GateRef a1 = acc_.GetValueIn(gate, 1); // 1:first parameter
|
||||
GateRef func = acc_.GetValueIn(gate, 2); // 2:function
|
||||
GateRef bcOffset = builder_.Int64(acc_.GetBytecodeIndex(gate));
|
||||
GateRef env = builder_.Undefined();
|
||||
|
||||
|
@ -13,8 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/builtins_lowering.h"
|
||||
#include "ecmascript/compiler/ts_type_lowering.h"
|
||||
#include "ecmascript/llvm_stackmap_parser.h"
|
||||
#include "ecmascript/ts_types/ts_type.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void TSTypeLowering::RunTSTypeLowering()
|
||||
@ -221,6 +223,9 @@ void TSTypeLowering::Lower(GateRef gate)
|
||||
case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
|
||||
LowerTypedSuperCall(gate, jsFunc, newTarget, glue);
|
||||
break;
|
||||
case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
|
||||
LowerCallThis1Imm8V8V8(gate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -829,7 +834,6 @@ void TSTypeLowering::LowerTypedLdObjByIndex(GateRef gate)
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
std::vector<GateRef> removedGate;
|
||||
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
|
||||
DeleteGates(gate, removedGate);
|
||||
@ -1038,4 +1042,55 @@ GateRef TSTypeLowering::GetSuperConstructor(GateRef ctor)
|
||||
GateRef protoOffset = builder_.IntPtr(JSHClass::PROTOTYPE_OFFSET);
|
||||
return builder_.Load(VariableType::JS_ANY(), hclass, protoOffset);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
void TSTypeLowering::SpeculateCallBuiltin(GateRef gate, BuiltinsStubCSigns::ID id)
|
||||
{
|
||||
GateRef function = acc_.GetValueIn(gate, 2); // 2:function
|
||||
GateRef a0 = acc_.GetValueIn(gate, 1);
|
||||
GateRef guard = acc_.GetDep(gate);
|
||||
ASSERT(acc_.GetOpCode(guard) == OpCode::GUARD);
|
||||
builder_.SetDepend(acc_.GetDep(guard));
|
||||
GateRef funcheck = builder_.CallTargetCheck(function, builder_.IntPtr(static_cast<int64_t>(id)));
|
||||
BuiltinLowering lowering(circuit_);
|
||||
GateRef paracheck = lowering.CheckPara(gate, id);
|
||||
GateRef check = builder_.BoolAnd(paracheck, funcheck);
|
||||
|
||||
acc_.ReplaceIn(guard, 1, check);
|
||||
builder_.SetDepend(guard);
|
||||
|
||||
GateRef result = builder_.TypedCallBuiltin(a0, id);
|
||||
std::vector<GateRef> removedGate;
|
||||
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
|
||||
DeleteGates(gate, removedGate);
|
||||
}
|
||||
|
||||
BuiltinsStubCSigns::ID TSTypeLowering::GetBuiltinId(GateRef func, GateRef receiver)
|
||||
{
|
||||
GateType receiverType = acc_.GetGateType(receiver);
|
||||
if (!tsManager_->IsBuiltinMath(receiverType)) {
|
||||
return BuiltinsStubCSigns::ID::NONE;
|
||||
}
|
||||
GateType funcType = acc_.GetGateType(func);
|
||||
if (!tsManager_->IsBuiltin(funcType)) {
|
||||
return BuiltinsStubCSigns::ID::NONE;
|
||||
}
|
||||
std::string name = tsManager_->GetFuncName(funcType);
|
||||
BuiltinsStubCSigns::ID id = BuiltinLowering::GetBuiltinId(name);
|
||||
return id;
|
||||
}
|
||||
|
||||
void TSTypeLowering::LowerCallThis1Imm8V8V8(GateRef gate)
|
||||
{
|
||||
GateRef thisObj = acc_.GetValueIn(gate, 0);
|
||||
GateRef a0 = acc_.GetValueIn(gate, 1); // 1:parameter index
|
||||
GateType a0Type = acc_.GetGateType(a0);
|
||||
GateRef func = acc_.GetValueIn(gate, 2); // 2:function
|
||||
BuiltinsStubCSigns::ID id = GetBuiltinId(func, thisObj);
|
||||
if (id != BuiltinsStubCSigns::ID::NONE && a0Type.IsNumberType()) {
|
||||
SpeculateCallBuiltin(gate, id);
|
||||
} else {
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
acc_.DeleteGuardAndFrameState(gate);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define ECMASCRIPT_COMPILER_TS_TYPE_LOWERING_H
|
||||
|
||||
#include "ecmascript/compiler/argument_accessor.h"
|
||||
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
|
||||
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
|
||||
@ -80,6 +81,7 @@ private:
|
||||
void LowerTypedSuperCall(GateRef gate, GateRef ctor, GateRef newTarget, GateRef glue);
|
||||
|
||||
GateRef GetSuperConstructor(GateRef ctor);
|
||||
void LowerCallThis1Imm8V8V8(GateRef gate);
|
||||
|
||||
// TypeTrusted means the type of gate is already typecheck-passed, or the gate is constant and no need to check.
|
||||
bool IsTrustedType(GateRef gate) const;
|
||||
@ -89,6 +91,8 @@ private:
|
||||
template<TypedUnOp Op>
|
||||
void SpeculateNumber(GateRef gate);
|
||||
void SpeculateConditionJump(GateRef gate);
|
||||
void SpeculateCallBuiltin(GateRef gate, BuiltinsStubCSigns::ID Op);
|
||||
BuiltinsStubCSigns::ID GetBuiltinId(GateRef func, GateRef receiver);
|
||||
template<TypedUnOp Op>
|
||||
GateRef AppendOverflowCheck(GateRef typeCheck, GateRef intVal);
|
||||
Circuit *circuit_ {nullptr};
|
||||
|
@ -13,6 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/builtins_lowering.h"
|
||||
#include "ecmascript/compiler/type_lowering.h"
|
||||
#include "ecmascript/deoptimizer.h"
|
||||
#include "ecmascript/js_arraybuffer.h"
|
||||
@ -77,6 +78,12 @@ void TypeLowering::LowerType(GateRef gate)
|
||||
case OpCode::CONSTRUCT:
|
||||
LowerConstruct(gate, glue);
|
||||
break;
|
||||
case OpCode::TYPED_CALL:
|
||||
LowerTypedCallBuitin(gate);
|
||||
break;
|
||||
case OpCode::TYPED_CALL_CHECK:
|
||||
LowerCallTargetCheck(gate);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2244,7 +2251,7 @@ GateRef TypeLowering::ModNumbers(GateRef left, GateRef right, GateType leftType,
|
||||
ArgumentAccessor argAcc(circuit_);
|
||||
auto glue = argAcc.GetCommonArgGate(CommonArgIdx::GLUE);
|
||||
result = builder_.CallNGCRuntime(
|
||||
glue, RTSTUB_ID(AotFloatMod), Gate::InvalidGateRef, { *doubleLeft, *doubleRight });
|
||||
glue, RTSTUB_ID(FloatMod), Gate::InvalidGateRef, { *doubleLeft, *doubleRight });
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
@ -2505,4 +2512,16 @@ GateRef TypeLowering::FastEqual(GateRef left, GateRef right)
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void TypeLowering::LowerTypedCallBuitin(GateRef gate)
|
||||
{
|
||||
BuiltinLowering lowering(circuit_);
|
||||
lowering.LowerTypedCallBuitin(gate);
|
||||
}
|
||||
|
||||
void TypeLowering::LowerCallTargetCheck(GateRef gate)
|
||||
{
|
||||
BuiltinLowering lowering(circuit_);
|
||||
lowering.LowerCallTargetCheck(gate);
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -183,6 +183,8 @@ private:
|
||||
void InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef glue, GateRef value,
|
||||
GateRef start, GateRef end);
|
||||
void LowerConstruct(GateRef gate, GateRef glue);
|
||||
void LowerTypedCallBuitin(GateRef gate);
|
||||
void LowerCallTargetCheck(GateRef gate);
|
||||
|
||||
GateRef LowerCallRuntime(GateRef glue, int index, const std::vector<GateRef> &args, bool useLabel = false);
|
||||
|
||||
|
@ -31,7 +31,7 @@ static std::array<std::string, MessageString::MAX_MESSAGE_COUNT> g_messageString
|
||||
DEF_ASM_INTERPRETER_STUB_MESSAGE)
|
||||
ASM_INTERPRETER_SECOND_BC_STUB_ID_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE)
|
||||
ASM_INTERPRETER_BC_HELPER_STUB_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE)
|
||||
BUILTINS_STUB_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE)
|
||||
ASM_INTERPRETER_BUILTINS_STUB_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE)
|
||||
#undef DEF_ASM_INTERPRETER_STUB_MESSAGE
|
||||
};
|
||||
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
ASM_INTERPRETER_BC_STUB_LIST(DEF_MESSAGE_ID, DEF_MESSAGE_ID, DEF_MESSAGE_ID)
|
||||
ASM_INTERPRETER_SECOND_BC_STUB_ID_LIST(DEF_MESSAGE_ID)
|
||||
ASM_INTERPRETER_BC_HELPER_STUB_LIST(DEF_MESSAGE_ID)
|
||||
BUILTINS_STUB_LIST(DEF_MESSAGE_ID)
|
||||
ASM_INTERPRETER_BUILTINS_STUB_LIST(DEF_MESSAGE_ID)
|
||||
#undef DEF_MESSAGE_ID
|
||||
MAX_MESSAGE_COUNT,
|
||||
ASM_INTERPRETER_START = Message_INT32_VALUE + 1,
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "ecmascript/base/error_helper.h"
|
||||
#include "ecmascript/builtins/builtins.h"
|
||||
#include "ecmascript/builtins/builtins_errors.h"
|
||||
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
#include "ecmascript/ecma_macros.h"
|
||||
#include "ecmascript/ecma_string_table.h"
|
||||
@ -149,7 +150,8 @@ JSHandle<Method> ObjectFactory::NewMethodForNativeFunction(const void *func, Fun
|
||||
method->SetNativePointer(const_cast<void *>(func));
|
||||
method->SetNativeBit(true);
|
||||
if (builtinId != INVALID_BUILTINS_ID) {
|
||||
method->SetFastBuiltinBit(true);
|
||||
bool isFast = kungfu::BuiltinsStubCSigns::IsFastBuiltin(static_cast<kungfu::BuiltinsStubCSigns::ID>(builtinId));
|
||||
method->SetFastBuiltinBit(isFast);
|
||||
method->SetBuiltinId(builtinId);
|
||||
}
|
||||
method->SetNumArgsWithCallField(numArgs);
|
||||
|
@ -13,7 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ecmascript/Relocator.h"
|
||||
#include "ecmascript/relocator.h"
|
||||
#include <climits>
|
||||
#include <iomanip>
|
||||
#include "ecmascript/compiler/assembler/aarch64/assembler_aarch64_constants.h"
|
||||
@ -113,7 +113,7 @@ bool Relocator::RelocateBySymbol(const char* symbol, uintptr_t patchAddr)
|
||||
}
|
||||
auto symId = GetSymbol(symbol);
|
||||
if (!symId.has_value()) {
|
||||
LOG_COMPILER(INFO) << " don't find symbol:" << symbol << " in symbol table.";
|
||||
LOG_COMPILER(DEBUG) << " don't find symbol:" << symbol << " in symbol table.";
|
||||
return false;
|
||||
}
|
||||
bool ret = RelocateBySymbolId(symId.value(), patchAddr);
|
@ -2123,15 +2123,39 @@ int32_t RuntimeStubs::FindElementWithCache(uintptr_t argGlue, JSTaggedType hclas
|
||||
return index;
|
||||
}
|
||||
|
||||
JSTaggedType RuntimeStubs::AotFloatMod(double x, double y)
|
||||
JSTaggedType RuntimeStubs::FloatMod(double x, double y)
|
||||
{
|
||||
double result = std::fmod(x, y);
|
||||
return JSTaggedValue(result).GetRawData();
|
||||
}
|
||||
|
||||
JSTaggedType RuntimeStubs::FloatMod(double x, double y)
|
||||
JSTaggedType RuntimeStubs::FloatSqrt(double x)
|
||||
{
|
||||
double result = std::fmod(x, y);
|
||||
double result = std::sqrt(x);
|
||||
return JSTaggedValue(result).GetRawData();
|
||||
}
|
||||
|
||||
JSTaggedType RuntimeStubs::FloatCos(double x)
|
||||
{
|
||||
double result = std::cos(x);
|
||||
return JSTaggedValue(result).GetRawData();
|
||||
}
|
||||
|
||||
JSTaggedType RuntimeStubs::FloatSin(double x)
|
||||
{
|
||||
double result = std::sin(x);
|
||||
return JSTaggedValue(result).GetRawData();
|
||||
}
|
||||
|
||||
JSTaggedType RuntimeStubs::FloatACos(double x)
|
||||
{
|
||||
double result = std::acos(x);
|
||||
return JSTaggedValue(result).GetRawData();
|
||||
}
|
||||
|
||||
JSTaggedType RuntimeStubs::FloatATan(double x)
|
||||
{
|
||||
double result = std::atan(x);
|
||||
return JSTaggedValue(result).GetRawData();
|
||||
}
|
||||
|
||||
|
@ -93,8 +93,12 @@ using JSFunctionEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, con
|
||||
V(MarkingBarrier) \
|
||||
V(StoreBarrier) \
|
||||
V(DoubleToInt) \
|
||||
V(AotFloatMod) \
|
||||
V(FloatMod) \
|
||||
V(FloatSqrt) \
|
||||
V(FloatCos) \
|
||||
V(FloatSin) \
|
||||
V(FloatACos) \
|
||||
V(FloatATan) \
|
||||
V(FindElementWithCache) \
|
||||
V(CreateArrayFromList) \
|
||||
V(StringsAreEquals) \
|
||||
@ -345,8 +349,12 @@ public:
|
||||
static JSTaggedType CreateArrayFromList([[maybe_unused]]uintptr_t argGlue, int32_t argc, JSTaggedValue *argv);
|
||||
static void InsertOldToNewRSet([[maybe_unused]]uintptr_t argGlue, uintptr_t object, size_t offset);
|
||||
static int32_t DoubleToInt(double x);
|
||||
static JSTaggedType AotFloatMod(double x, double y);
|
||||
static JSTaggedType FloatMod(double x, double y);
|
||||
static JSTaggedType FloatSqrt(double x);
|
||||
static JSTaggedType FloatCos(double x);
|
||||
static JSTaggedType FloatSin(double x);
|
||||
static JSTaggedType FloatACos(double x);
|
||||
static JSTaggedType FloatATan(double x);
|
||||
static int32_t FindElementWithCache(uintptr_t argGlue, JSTaggedType hclass,
|
||||
JSTaggedType key, int32_t num);
|
||||
static bool StringsAreEquals(EcmaString *str1, EcmaString *str2);
|
||||
|
@ -684,6 +684,19 @@ JSHandle<TSTypeTable> TSManager::GetRuntimeTypeTable() const
|
||||
return runtimeTable;
|
||||
}
|
||||
|
||||
std::string TSManager::GetFuncName(kungfu::GateType type) const
|
||||
{
|
||||
GlobalTSTypeRef gt = type.GetGTRef();
|
||||
ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
|
||||
JSHandle<JSTaggedValue> tsType = GetTSType(gt);
|
||||
ASSERT(tsType->IsTSFunctionType());
|
||||
JSHandle<TSFunctionType> functionType = JSHandle<TSFunctionType>(tsType);
|
||||
auto name = functionType->GetName();
|
||||
EcmaStringAccessor acc(name);
|
||||
std::string nameStr = acc.ToStdString();
|
||||
return nameStr;
|
||||
}
|
||||
|
||||
uint32_t TSManager::GetFunctionTypeLength(GlobalTSTypeRef gt) const
|
||||
{
|
||||
ASSERT(GetTypeKind(gt) == TSTypeKind::FUNCTION);
|
||||
@ -1055,6 +1068,30 @@ void TSManager::ResolveSnapshotConstantPool(const std::map<uint32_t, uint32_t> &
|
||||
}
|
||||
}
|
||||
|
||||
bool TSManager::IsBuiltinMath(kungfu::GateType funcType) const
|
||||
{
|
||||
GlobalTSTypeRef funcGt = funcType.GetGTRef();
|
||||
uint32_t moduleId = funcGt.GetModuleId();
|
||||
if (moduleId != static_cast<uint32_t>(MTableIdx::BUILTIN)) {
|
||||
return false;
|
||||
}
|
||||
uint32_t localId = funcGt.GetLocalId();
|
||||
if (localId == TSManager::BUILTINS_MATH_ID) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TSManager::IsBuiltin(kungfu::GateType funcType) const
|
||||
{
|
||||
GlobalTSTypeRef funcGt = funcType.GetGTRef();
|
||||
uint32_t moduleId = funcGt.GetModuleId();
|
||||
if (moduleId != static_cast<uint32_t>(MTableIdx::BUILTIN)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TSModuleTable::Initialize(JSThread *thread, JSHandle<TSModuleTable> mTable)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
|
@ -237,6 +237,8 @@ public:
|
||||
|
||||
GlobalTSTypeRef PUBLIC_API GetFuncReturnValueTypeGT(GlobalTSTypeRef gt) const;
|
||||
|
||||
std::string PUBLIC_API GetFuncName(kungfu::GateType gt) const;
|
||||
|
||||
inline GlobalTSTypeRef PUBLIC_API GetArrayParameterTypeGT(kungfu::GateType gateType) const
|
||||
{
|
||||
GlobalTSTypeRef gt = gateType.GetGTRef();
|
||||
@ -346,6 +348,7 @@ public:
|
||||
static constexpr int BUILTIN_FLOAT32_ARRAY_ID = 33;
|
||||
static constexpr int BUILTIN_TYPED_ARRAY_LAST_ID = 36;
|
||||
static constexpr int BUILTIN_STRING_ID = 39;
|
||||
static constexpr int BUILTINS_MATH_ID = 53; // fix number by front
|
||||
|
||||
bool PUBLIC_API IsTypedArrayType(kungfu::GateType gateType) const;
|
||||
|
||||
@ -505,6 +508,10 @@ public:
|
||||
return JSHandle<JSTaggedValue>(uintptr_t(&snapshotConstantPool_));
|
||||
}
|
||||
|
||||
bool PUBLIC_API IsBuiltin(kungfu::GateType funcType) const;
|
||||
|
||||
bool PUBLIC_API IsBuiltinMath(kungfu::GateType funcType) const;
|
||||
|
||||
private:
|
||||
NO_COPY_SEMANTIC(TSManager);
|
||||
NO_MOVE_SEMANTIC(TSManager);
|
||||
|
@ -37,6 +37,7 @@ group("ark_aot_test") {
|
||||
"ashr:ashrAotAction",
|
||||
"asyncgenerator:asyncgeneratorAotAction",
|
||||
"bind:bindAotAction",
|
||||
"builtinmath:builtinmathAotAction",
|
||||
"call_same_bytecode_func:call_same_bytecode_funcAotAction",
|
||||
"callithisrange:callithisrangeAotAction",
|
||||
"calls:callsAotAction",
|
||||
|
@ -15,5 +15,4 @@ import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_aot_test_action("typemod") {
|
||||
deps = []
|
||||
is_disable_type_lowering = true
|
||||
}
|
||||
|
19
test/aottest/builtinmath/BUILD.gn
Normal file
19
test/aottest/builtinmath/BUILD.gn
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2022 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("builtinmath") {
|
||||
deps = []
|
||||
is_disable_type_lowering = true
|
||||
}
|
44
test/aottest/builtinmath/builtinmath.ts
Normal file
44
test/aottest/builtinmath/builtinmath.ts
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
declare function print(arg:any):string;
|
||||
let len:number = 1;
|
||||
len = 1 / Math.sqrt(len);
|
||||
print(len);
|
||||
|
||||
len = 9 / len;
|
||||
len = Math.sqrt(len);
|
||||
print(len);
|
||||
print(NaN);
|
||||
len = Math.sqrt(NaN);
|
||||
print(len);
|
||||
|
||||
len = Math.cos(0); // 1
|
||||
print(len);
|
||||
len = Math.cos(1); // 0.5....
|
||||
print(len);
|
||||
|
||||
len = Math.sin(0); // 0
|
||||
print(len);
|
||||
len = Math.sin(1); // 0.84
|
||||
print(len);
|
||||
len = Math.sin(Math.PI / 2);
|
||||
print(len);
|
||||
|
||||
len = Math.acos(0.5);// 1.0471975511965979
|
||||
print(len);
|
||||
|
||||
len = Math.atan(2); // 1.1071487177940904
|
||||
print(len);
|
||||
|
24
test/aottest/builtinmath/expect_output.txt
Normal file
24
test/aottest/builtinmath/expect_output.txt
Normal file
@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2022 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.
|
||||
|
||||
1
|
||||
3
|
||||
NaN
|
||||
NaN
|
||||
1
|
||||
0.5403023058681398
|
||||
0
|
||||
0.8414709848078965
|
||||
1
|
||||
1.0471975511965979
|
||||
1.1071487177940904
|
Loading…
Reference in New Issue
Block a user