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:
songzhengchao 2022-11-10 18:01:26 +08:00
commit db10160072
38 changed files with 789 additions and 60 deletions

View File

@ -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",

View File

@ -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"

View File

@ -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);

View File

@ -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",

View File

@ -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]);
}
}

View File

@ -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_;

View File

@ -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

View 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, &notNumberBranch);
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(&notNumberBranch);
{
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, &notNumberBranch);
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, &notSignbit);
builder_.Bind(&signbit);
{
result = builder_.DoubleToTaggedDoublePtr(builder_.Double(base::NAN_VALUE));
builder_.Jump(&exit);
}
builder_.Bind(&notSignbit);
{
Label naN(&builder_);
Label notNan(&builder_);
GateRef condition = builder_.DoubleIsNAN(*value);
builder_.Branch(condition, &naN, &notNan);
builder_.Bind(&notNan);
{
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(&notNumberBranch);
{
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, &notHeapObject);
builder_.Bind(&notHeapObject);
{
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

View 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

View File

@ -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:

View File

@ -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

View File

@ -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) \

View File

@ -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();

View File

@ -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)
{

View File

@ -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_;

View File

@ -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

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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};

View File

@ -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

View File

@ -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);

View File

@ -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
};

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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();
}

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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",

View File

@ -15,5 +15,4 @@ import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_test_action("typemod") {
deps = []
is_disable_type_lowering = true
}

View 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
}

View 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);

View 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