[feature]:dataview.prototype.get arraybuffer.isview aot nativeinline

[issue]:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I9CQIH

Signed-off-by: luobinghao <luobinghao@huawei.com>
Change-Id: I14b564d828a926198ad558874c90a043a5ea7f24
This commit is contained in:
luobinghao 2024-04-02 11:39:00 +08:00
parent e806c4560c
commit c2a8fe67e6
24 changed files with 1239 additions and 42 deletions

View File

@ -141,7 +141,7 @@ public:
const uint8_t *end, JSTaggedValue string);
static double StringToDouble(const uint8_t *start, const uint8_t *end, uint8_t radix, uint32_t flags = NO_FLAGS);
static int32_t DoubleToInt(double d, size_t bits);
static int32_t DoubleInRangeInt32(double d);
static int32_t PUBLIC_API DoubleInRangeInt32(double d);
static JSTaggedValue StringToDoubleWithRadix(const uint8_t *start, const uint8_t *end, int radix, bool *negative);
static CString IntToString(int number);
static CString IntegerToString(double number, int radix);

View File

@ -2271,7 +2271,14 @@ void Builtins::InitializeArrayBuffer(const JSHandle<GlobalEnv> &env, const JSHan
SetFunction(env, arrayBufferFuncPrototype, "slice", ArrayBuffer::Slice, FunctionLength::TWO);
// ArrayBuffer method
SetFunction(env, arrayBufferFunction, "isView", ArrayBuffer::IsView, FunctionLength::ONE);
for (const base::BuiltinFunctionEntry& entry: ArrayBuffer::GetArrayBufferFunctions()) {
SetFunction(env,
arrayBufferFunction,
entry.GetName(),
entry.GetEntrypoint(),
entry.GetLength(),
entry.GetBuiltinStubId());
}
// 24.1.3.3 get ArrayBuffer[@@species]
JSHandle<JSTaggedValue> speciesSymbol = env->GetSpeciesSymbol();

View File

@ -21,6 +21,14 @@
#include "ecmascript/js_dataview.h"
#include "ecmascript/js_typed_array.h"
// List of functions in ArrayBuffer, excluding the '@@' properties.
// V(name, func, length, stubIndex)
// where BuiltinsArrayBuffer::func refers to the native implementation of ArrayBuffer[name].
// kungfu::BuiltinsStubCSigns::stubIndex refers to the builtin stub index, or INVALID if no stub available.
#define BUILTIN_ARRAY_BUFFER_FUNCTIONS(V) \
/* ArrayBuffer.isView ( arg ) */ \
V("isView", IsView, 1, ArrayBufferIsView)
namespace panda::ecmascript::builtins {
static constexpr double NUMBER_HALF = 0.5;
static constexpr uint32_t BITS_EIGHT = 8;
@ -72,6 +80,12 @@ public:
// es12 25.1.2.7 IsBigIntElementType ( type )
static bool IsBigIntElementType(DataViewType type);
// Excluding the '@@' internal properties
static Span<const base::BuiltinFunctionEntry> GetArrayBufferFunctions()
{
return Span<const base::BuiltinFunctionEntry>(ARRAY_BUFFER_FUNCTIONS);
}
static JSTaggedValue FastSetValueInBuffer(JSThread* thread, JSTaggedValue arrBuf, uint32_t byteIndex,
DataViewType type, double val, bool littleEndian);
static JSTaggedValue TryFastSetValueInBuffer(JSThread *thread, JSTaggedValue arrBuf, uint32_t byteBeginOffset,
@ -98,6 +112,12 @@ public:
static void *GetDataPointFromBuffer(JSTaggedValue arrBuf, uint32_t byteOffset = 0);
private:
#define BUILTIN_ARRAY_BUFFER_ENTRY(name, func, length, id) \
base::BuiltinFunctionEntry::Create((name), (BuiltinsArrayBuffer::func), (length), (kungfu::BuiltinsStubCSigns::id)),
static constexpr std::array ARRAY_BUFFER_FUNCTIONS = {BUILTIN_ARRAY_BUFFER_FUNCTIONS(BUILTIN_ARRAY_BUFFER_ENTRY)};
#undef BUILTIN_ARRAY_BUFFER_ENTRY
template <typename T>
static T LittleEndianToBigEndian(T liValue);
template<typename T>

View File

@ -28,29 +28,29 @@
/* DataView.prototype.get%Type% ( byteOffset ) */ \
/* For %Type% of 2 or more bytes: */ \
/* DataView.prototype.get%Type% ( byteOffset [ , littleEndian ] ) */ \
V("getFloat32", GetFloat32, 1, INVALID) \
V("getFloat64", GetFloat64, 1, INVALID) \
V("getInt8", GetInt8, 1, INVALID) \
V("getInt16", GetInt16, 1, INVALID) \
V("getInt32", GetInt32, 1, INVALID) \
V("getBigInt64", GetBigInt64, 1, INVALID) \
V("getUint16", GetUint16, 1, INVALID) \
V("getUint32", GetUint32, 1, INVALID) \
V("getUint8", GetUint8, 1, INVALID) \
V("getBigUint64", GetBigUint64, 1, INVALID) \
V("getFloat32", GetFloat32, 1, DataViewGetFloat32 ) \
V("getFloat64", GetFloat64, 1, DataViewGetFloat64 ) \
V("getInt8", GetInt8, 1, DataViewGetInt8 ) \
V("getInt16", GetInt16, 1, DataViewGetInt16 ) \
V("getInt32", GetInt32, 1, DataViewGetInt32 ) \
V("getBigInt64", GetBigInt64, 1, INVALID ) \
V("getUint16", GetUint16, 1, DataViewGetUint16 ) \
V("getUint32", GetUint32, 1, DataViewGetUint32 ) \
V("getUint8", GetUint8, 1, DataViewGetUint8 ) \
V("getBigUint64", GetBigUint64, 1, INVALID ) \
/* For %Type% of 1 bytes: */ \
/* DataView.prototype.setInt8 ( byteOffset, value ) */ \
/* For %Type% of 2 or more bytes: */ \
/* DataView.prototype.setInt16 ( byteOffset, value [ , littleEndian ] ) */ \
V("setFloat32", SetFloat32, 2, INVALID) \
V("setFloat64", SetFloat64, 2, INVALID) \
V("setInt8", SetInt8, 2, INVALID) \
V("setInt16", SetInt16, 2, INVALID) \
V("setInt32", SetInt32, 2, INVALID) \
V("setFloat32", SetFloat32, 2, DataViewSetFloat32) \
V("setFloat64", SetFloat64, 2, DataViewSetFloat64) \
V("setInt8", SetInt8, 2, DataViewSetInt8) \
V("setInt16", SetInt16, 2, DataViewSetInt16) \
V("setInt32", SetInt32, 2, DataViewSetInt32) \
V("setBigInt64", SetBigInt64, 2, INVALID) \
V("setUint8", SetUint8, 2, INVALID) \
V("setUint16", SetUint16, 2, INVALID) \
V("setUint32", SetUint32, 2, INVALID) \
V("setUint8", SetUint8, 2, DataViewSetUint8) \
V("setUint16", SetUint16, 2, DataViewSetUint16) \
V("setUint32", SetUint32, 2, DataViewSetUint32) \
V("setBigUint64", SetBigUint64, 2, INVALID)
namespace panda::ecmascript::builtins {

View File

@ -203,8 +203,25 @@ namespace panda::ecmascript::kungfu {
V(MathImul) \
V(GlobalIsFinite) \
V(GlobalIsNan) \
V(ArrayBufferIsView) \
V(DataViewGetFloat32) \
V(DataViewGetFloat64) \
V(DataViewGetInt8) \
V(DataViewGetInt16) \
V(DataViewGetInt32) \
V(DataViewGetUint16) \
V(DataViewGetUint32) \
V(DataViewGetUint8) \
V(DataViewSetFloat32) \
V(DataViewSetFloat64) \
V(DataViewSetInt8) \
V(DataViewSetInt16) \
V(DataViewSetInt32) \
V(DataViewSetUint8) \
V(DataViewSetUint16) \
V(DataViewSetUint32) \
V(TYPED_BUILTINS_INLINE_FIRST = MathAcos) \
V(TYPED_BUILTINS_INLINE_LAST = GlobalIsNan)
V(TYPED_BUILTINS_INLINE_LAST = DataViewSetUint32)
class BuiltinsStubCSigns {
public:
@ -400,6 +417,40 @@ public:
return ConstantIndex::GLOBAL_IS_FINITE_INDEX;
case BuiltinsStubCSigns::ID::GlobalIsNan:
return ConstantIndex::GLOBAL_IS_NAN_INDEX;
case BuiltinsStubCSigns::ID::ArrayBufferIsView:
return ConstantIndex::ARRAY_BUFFER_IS_VIEW_INDEX;
case BuiltinsStubCSigns::ID::DataViewGetFloat32:
return ConstantIndex::DATA_VIEW_GET_FLOAT32_INDEX;
case BuiltinsStubCSigns::ID::DataViewGetFloat64:
return ConstantIndex::DATA_VIEW_GET_FLOAT64_INDEX;
case BuiltinsStubCSigns::ID::DataViewGetInt8:
return ConstantIndex::DATA_VIEW_GET_INT8_INDEX;
case BuiltinsStubCSigns::ID::DataViewGetInt16:
return ConstantIndex::DATA_VIEW_GET_INT16_INDEX;
case BuiltinsStubCSigns::ID::DataViewGetInt32:
return ConstantIndex::DATA_VIEW_GET_INT32_INDEX;
case BuiltinsStubCSigns::ID::DataViewGetUint16:
return ConstantIndex::DATA_VIEW_GET_UINT16_INDEX;
case BuiltinsStubCSigns::ID::DataViewGetUint32:
return ConstantIndex::DATA_VIEW_GET_UINT32_INDEX;
case BuiltinsStubCSigns::ID::DataViewGetUint8:
return ConstantIndex::DATA_VIEW_GET_UINT8_INDEX;
case BuiltinsStubCSigns::ID::DataViewSetFloat32:
return ConstantIndex::DATA_VIEW_SET_FLOAT32_INDEX;
case BuiltinsStubCSigns::ID::DataViewSetFloat64:
return ConstantIndex::DATA_VIEW_SET_FLOAT64_INDEX;
case BuiltinsStubCSigns::ID::DataViewSetInt8:
return ConstantIndex::DATA_VIEW_SET_INT8_INDEX;
case BuiltinsStubCSigns::ID::DataViewSetInt16:
return ConstantIndex::DATA_VIEW_SET_INT16_INDEX;
case BuiltinsStubCSigns::ID::DataViewSetInt32:
return ConstantIndex::DATA_VIEW_SET_INT32_INDEX;
case BuiltinsStubCSigns::ID::DataViewSetUint8:
return ConstantIndex::DATA_VIEW_SET_UINT8_INDEX;
case BuiltinsStubCSigns::ID::DataViewSetUint16:
return ConstantIndex::DATA_VIEW_SET_UINT16_INDEX;
case BuiltinsStubCSigns::ID::DataViewSetUint32:
return ConstantIndex::DATA_VIEW_SET_UINT32_INDEX;
default:
LOG_COMPILER(FATAL) << "this branch is unreachable";
UNREACHABLE();

View File

@ -22,16 +22,17 @@
#include "ecmascript/compiler/lcr_circuit_builder.h"
#include "ecmascript/compiler/mcr_circuit_builder.h"
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/global_env.h"
#include "ecmascript/ic/proto_change_details.h"
#include "ecmascript/js_array_iterator.h"
#include "ecmascript/js_for_in_iterator.h"
#include "ecmascript/js_function.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/mem/region.h"
#include "ecmascript/method.h"
#include "ecmascript/js_array_iterator.h"
namespace panda::ecmascript::kungfu {
@ -738,6 +739,28 @@ GateRef CircuitBuilder::IsEcmaObject(GateRef obj)
return ret;
}
GateRef CircuitBuilder::CheckJSType(GateRef object, JSType jsType)
{
Label entryPass(env_);
SubCfgEntry(&entryPass);
DEFVALUE(result, env_, VariableType::BOOL(), False());
Label heapObj(env_);
Label exit(env_);
GateRef isHeapObject = TaggedIsHeapObject(object);
BRANCH_CIR2(isHeapObject, &heapObj, &exit);
Bind(&heapObj);
{
GateRef objectType = GetObjectType(LoadHClass(object));
GateRef checkType = Int32Equal(objectType, Int32(static_cast<int32_t>(jsType)));
result = LogicAnd(isHeapObject, checkType);
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
SubCfgExit();
return ret;
}
GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module,
GateRef index, ConstPoolType type)
{

View File

@ -19,19 +19,20 @@
#include "ecmascript/base/number_helper.h"
#include "ecmascript/compiler/assembler/assembler.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/call_signature.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/gate.h"
#include "ecmascript/compiler/gate_accessor.h"
#include "ecmascript/compiler/lcr_gate_meta_data.h"
#include "ecmascript/compiler/pgo_type/pgo_type_location.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/compiler/variable_type.h"
#include "ecmascript/global_env_constants.h"
#include "ecmascript/compiler/pgo_type/pgo_type_location.h"
#include "ecmascript/jspandafile/constpool_value.h"
#include "ecmascript/js_hclass.h"
#include "ecmascript/js_runtime_options.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/jspandafile/constpool_value.h"
#include "ecmascript/tagged_array.h"
#include <cstdint>
namespace panda::ecmascript::kungfu {
using namespace panda::ecmascript;
@ -106,6 +107,7 @@ class PostSchedule;
V(CastDoubleToInt64, Bitcast, MachineType::I64) \
V(CastInt64ToFloat64, Bitcast, MachineType::F64) \
V(CastInt32ToFloat32, Bitcast, MachineType::F32) \
V(CaseFloat32ToInt32, Bitcast, MachineType::I32) \
V(SExtInt32ToInt64, Sext, MachineType::I64) \
V(SExtInt1ToInt64, Sext, MachineType::I64) \
V(SExtInt1ToInt32, Sext, MachineType::I32) \
@ -218,6 +220,7 @@ public:
GateRef IsJsCOWArray(GateRef obj);
GateRef IsCOWArray(GateRef objectType);
GateRef IsTaggedArray(GateRef object);
GateRef CheckJSType(GateRef object, JSType jsType);
GateRef IsMutantTaggedArray(GateRef objectType);
GateRef SwitchCase(GateRef switchBranch, int64_t value);
GateRef Int8(int8_t val);
@ -530,6 +533,9 @@ public:
GateRef LexVarIsHoleCheck(GateRef value);
GateRef IsUndefinedOrHoleCheck(GateRef value);
GateRef IsNotUndefinedOrHoleCheck(GateRef value);
GateRef IsEcmaObjectCheck(GateRef obj);
GateRef IsDataViewCheck(GateRef obj);
GateRef IsTaggedBooleanCheck(GateRef value);
GateRef Int32UnsignedUpperBoundCheck(GateRef value, GateRef upperBound);
GateRef Int32DivWithCheck(GateRef left, GateRef right);
GateType GetGateTypeOfValueType(ValueType type);
@ -692,6 +698,8 @@ public:
inline GateRef TaggedObjectIsShared(GateRef obj);
inline GateRef TaggedObjectBothAreString(GateRef x, GateRef y);
inline GateRef TaggedObjectIsEcmaObject(GateRef obj);
inline GateRef TaggedObjectIsByteArray(GateRef obj);
inline GateRef TaggedObjectIsDataView(GateRef obj);
inline GateRef IsSpecialHole(GateRef x);
inline GateRef IsNotSpecialHole(GateRef x);
inline GateRef TaggedTrue();
@ -728,6 +736,15 @@ public:
GateRef charSize, VariableType type);
void SetRawHashcode(GateRef glue, GateRef str, GateRef rawHashcode, GateRef isInteger);
GateRef StringFromSingleCharCode(GateRef gate);
GateRef ArrayBufferIsView(GateRef gate);
GateRef DataViewGet(
GateRef thisobj, GateRef index, GateRef dataViewCallID, GateRef isLittleEndian, GateRef frameState);
GateRef DataViewSet(GateRef thisobj,
GateRef index,
GateRef value,
GateRef dataViewCallID,
GateRef isLittleEndian,
GateRef frameState);
GateRef ToNumber(GateRef gate, GateRef value, GateRef glue);
GateRef IsASCIICharacter(GateRef gate);
@ -778,6 +795,9 @@ public:
MemoryOrder order = MemoryOrder::Default());
// cast operation
inline GateRef Int16ToBigEndianInt16(GateRef x);
inline GateRef Int32ToBigEndianInt32(GateRef x);
inline GateRef Int64ToBigEndianInt64(GateRef x);
inline GateRef GetInt64OfTInt(GateRef x);
inline GateRef GetInt32OfTInt(GateRef x);
inline GateRef TaggedCastToIntPtr(GateRef x);
@ -787,6 +807,8 @@ public:
inline GateRef GetDoubleOfTNumber(GateRef x);
inline GateRef DoubleToInt(GateRef x, Label *exit);
inline GateRef DoubleToInt(GateRef glue, GateRef x, size_t typeBits);
inline GateRef DoubleCheckINFInRangeInt32(GateRef x);
inline GateRef DoubleInRangeInt32(GateRef x);
inline GateRef Int32ToTaggedPtr(GateRef x);
inline GateRef Int64ToTaggedPtr(GateRef x);
inline GateRef Int32ToTaggedInt(GateRef x);

View File

@ -16,7 +16,9 @@
#ifndef ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H
#define ECMASCRIPT_COMPILER_LCR_CIRCUIT_BUILDER_H
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/circuit_builder_helper.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/mem/region.h"
#include "ecmascript/method.h"
@ -74,6 +76,51 @@ GateRef CircuitBuilder::IntPtrLSL(GateRef x, GateRef y)
return BinaryArithmetic(circuit_->Lsl(), ptrSize, x, y);
}
GateRef CircuitBuilder::Int16ToBigEndianInt16(GateRef x)
{
GateRef int16toint32 = ZExtInt16ToInt32(x);
GateRef high8bits = Int32LSL(Int32And(int16toint32, Int32(0x00FF)), Int32(8));
GateRef low8bits = Int32LSR(Int32And(int16toint32, Int32(0xFF00)), Int32(8));
return TruncInt32ToInt16(Int32Add(high8bits, low8bits));
}
GateRef CircuitBuilder::Int32ToBigEndianInt32(GateRef x)
{
GateRef first8bits = Int32LSL(Int32And(x, Int32(0x000000FF)), Int32(24));
GateRef second8bits = Int32LSL(Int32And(x, Int32(0x0000FF00)), Int32(8));
GateRef third8bits = Int32LSR(Int32And(x, Int32(0x00FF0000)), Int32(8));
GateRef fourth8bits = Int32LSR(Int32And(x, Int32(0xFF000000)), Int32(24));
GateRef firstHalf = Int32Add(first8bits, second8bits);
GateRef secondHalf = Int32Add(third8bits, fourth8bits);
return Int32Add(firstHalf, secondHalf);
}
GateRef CircuitBuilder::Int64ToBigEndianInt64(GateRef x)
{
GateRef first8bits = Int64LSL(Int64And(x, Int64(0x00000000000000FF)), Int64(56));
GateRef second8bits = Int64LSL(Int64And(x, Int64(0x000000000000FF00)), Int64(40));
// 0-16bits
GateRef first16bits = Int64Add(first8bits, second8bits);
GateRef third8bits = Int64LSL(Int64And(x, Int64(0x0000000000FF0000)), Int64(24));
GateRef fourth8bits = Int64LSL(Int64And(x, Int64(0x00000000FF000000)), Int64(8));
// 16-32bits
GateRef second16bits = Int64Add(third8bits, fourth8bits);
// 0-32bits
GateRef firstHalf = Int64Add(first16bits, second16bits);
GateRef fifth8bits = Int64LSR(Int64And(x, Int64(0x000000FF00000000)), Int64(8));
GateRef sixth8bits = Int64LSR(Int64And(x, Int64(0x0000FF0000000000)), Int64(24));
//32-48bits
GateRef third16bits = Int64Add(fifth8bits, sixth8bits);
GateRef seventh8bits = Int64LSR(Int64And(x, Int64(0x00FF000000000000)), Int64(40));
GateRef eighth8bits = Int64LSR(Int64And(x, Int64(0xFF00000000000000)), Int64(56));
//48-64bits
GateRef fourth16bits = Int64Add(seventh8bits, eighth8bits);
//32-64bits
GateRef secondHalf = Int64Add(third16bits, fourth16bits);
//0-64bits
return Int64Add(firstHalf, secondHalf);
}
GateRef CircuitBuilder::IntPtrOr(GateRef x, GateRef y)
{
auto ptrsize = env_->Is32Bit() ? MachineType::I32 : MachineType::I64;
@ -208,6 +255,73 @@ GateRef CircuitBuilder::DoubleToInt(GateRef glue, GateRef x, size_t typeBits)
return ret;
}
GateRef CircuitBuilder::DoubleCheckINFInRangeInt32(GateRef x)
{
Label entry(env_);
env_->SubCfgEntry(&entry);
Label exit(env_);
Label isInfinity(env_);
Label positiveInf(env_);
Label negativeInf(env_);
DEFVALUE(result, env_, VariableType::INT32(), DoubleInRangeInt32(x));
GateRef Max = Double(INT32_MAX);
GateRef Min = Double(INT32_MIN);
GateRef pInfinity = Double(base::POSITIVE_INFINITY);
Branch(DoubleIsINF(x), &isInfinity, &exit);
Bind(&isInfinity);
{
Branch(DoubleEqual(x, pInfinity), &positiveInf, &negativeInf);
Bind(&positiveInf);
{
result = ChangeFloat64ToInt32(Max);
Jump(&exit);
}
Bind(&negativeInf);
{
result = ChangeFloat64ToInt32(Min);
Jump(&exit);
}
}
Bind(&exit);
auto ret = *result;
env_->SubCfgExit();
return ret;
}
GateRef CircuitBuilder::DoubleInRangeInt32(GateRef x)
{
Label entry(env_);
env_->SubCfgEntry(&entry);
Label exit(env_);
Label overflow(env_);
Label checkUnderflow(env_);
Label underflow(env_);
DEFVALUE(result, env_, VariableType::INT32(), ChangeFloat64ToInt32(x));
GateRef Max = Double(INT32_MAX);
GateRef Min = Double(INT32_MIN);
Branch(DoubleGreaterThan(x, Max), &overflow, &checkUnderflow);
Bind(&overflow);
{
result = ChangeFloat64ToInt32(Max);
Jump(&exit);
}
Bind(&checkUnderflow);
{
Branch(DoubleLessThan(x, Min), &underflow, &exit);
Bind(&underflow);
{
result = ChangeFloat64ToInt32(Min);
Jump(&exit);
}
}
Bind(&exit);
auto ret = *result;
env_->SubCfgExit();
return ret;
}
GateRef CircuitBuilder::Int32ToTaggedInt(GateRef x)
{
GateRef val = SExtInt32ToInt64(x);

View File

@ -16,6 +16,9 @@
#include "libpandabase/utils/hash.h"
#include "ecmascript/compiler/mcr_circuit_builder.h"
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/message_string.h"
#include "ecmascript/stubs/runtime_stubs-inl.h"
#include "ecmascript/stubs/runtime_stubs.h"
@ -714,6 +717,51 @@ GateRef CircuitBuilder::IsNotUndefinedOrHoleCheck(GateRef value)
return ret;
}
GateRef CircuitBuilder::IsEcmaObjectCheck(GateRef gate)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
GateRef ret = GetCircuit()->NewGate(circuit_->IsEcmaObjectCheck(),
MachineType::I1,
{currentControl, currentDepend, gate, frameState},
GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::IsDataViewCheck(GateRef gate)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
GateRef ret = GetCircuit()->NewGate(circuit_->IsDataViewCheck(),
MachineType::I1,
{currentControl, currentDepend, gate, frameState},
GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::IsTaggedBooleanCheck(GateRef value)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
auto frameState = acc_.FindNearestFrameState(currentDepend);
GateRef ret = GetCircuit()->NewGate(circuit_->IsTaggedBooleanCheck(),
MachineType::I1,
{currentControl, currentDepend, value, frameState},
GateType::NJSValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::ValueCheckNegOverflow(GateRef value)
{
auto currentLabel = env_->GetCurrentLabel();
@ -1636,6 +1684,50 @@ GateRef CircuitBuilder::StringFromSingleCharCode(GateRef gate)
return ret;
}
GateRef CircuitBuilder::ArrayBufferIsView(GateRef gate)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
GateRef ret = GetCircuit()->NewGate(
circuit_->ArrayBufferIsView(), MachineType::I64, {currentControl, currentDepend, gate}, GateType::AnyType());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::DataViewGet(
GateRef thisobj, GateRef index, GateRef dataViewCallID, GateRef isLittleEndian, GateRef frameState)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
GateRef ret = GetCircuit()->NewGate(
circuit_->DataViewGet(),
MachineType::I64,
{currentControl, currentDepend, thisobj, index, dataViewCallID, isLittleEndian, frameState},
GateType::AnyType());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::DataViewSet(
GateRef thisobj, GateRef index, GateRef value, GateRef dataViewCallID, GateRef isLittleEndian, GateRef frameState)
{
auto currentLabel = env_->GetCurrentLabel();
auto currentControl = currentLabel->GetControl();
auto currentDepend = currentLabel->GetDepend();
GateRef ret = GetCircuit()->NewGate(
circuit_->DataViewSet(),
MachineType::I64,
{currentControl, currentDepend, thisobj, index, value, dataViewCallID, isLittleEndian, frameState},
GateType::TaggedValue());
currentLabel->SetControl(ret);
currentLabel->SetDepend(ret);
return ret;
}
GateRef CircuitBuilder::IsASCIICharacter(GateRef gate)
{
return Int32UnsignedLessThan(Int32Sub(gate, Int32(1)), Int32(base::utf_helper::UTF8_1B_MAX));

View File

@ -88,6 +88,18 @@ GateRef CircuitBuilder::TaggedObjectIsEcmaObject(GateRef obj)
Int32GreaterThanOrEqual(objectType, Int32(static_cast<int32_t>(JSType::ECMA_OBJECT_FIRST))));
}
GateRef CircuitBuilder::TaggedObjectIsByteArray(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::BYTE_ARRAY)));
}
GateRef CircuitBuilder::TaggedObjectIsDataView(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));
return Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::JS_DATA_VIEW)));
}
GateRef CircuitBuilder::IsSpecialSlicedString(GateRef obj)
{
GateRef objectType = GetObjectType(LoadHClass(obj));

View File

@ -13,14 +13,16 @@
* limitations under the License.
*/
#include "ecmascript/compiler/mcr_lowering.h"
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/compiler/share_opcodes.h"
#include "ecmascript/global_env.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/js_function.h"
#include "ecmascript/js_hclass.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/jspandafile/program_object.h"
#include "ecmascript/message_string.h"
#include "ecmascript/compiler/argument_accessor.h"
namespace panda::ecmascript::kungfu {
@ -103,6 +105,15 @@ GateRef MCRLowering::VisitGate(GateRef gate)
case OpCode::IS_NOT_UNDEFINED_OR_HOLE_CHECK:
LowerIsNotUndefinedOrHoleCheck(gate);
break;
case OpCode::IS_ECMA_OBJECT_CHECK:
LowerIsEcmaObjectCheck(gate);
break;
case OpCode::IS_TAGGED_BOOLEAN_CHECK:
LowerIsTaggedBooleanCheck(gate);
break;
case OpCode::IS_DATA_VIEW_CHECK:
LowerIsDataViewCheck(gate);
break;
case OpCode::STORE_MEMORY:
LowerStoreMemory(gate);
break;
@ -914,6 +925,36 @@ void MCRLowering::LowerIsNotUndefinedOrHoleCheck(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void MCRLowering::LowerIsEcmaObjectCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef frameState = acc_.GetFrameState(gate);
GateRef obj = acc_.GetValueIn(gate, 0);
GateRef isEcmaObject = builder_.IsEcmaObject(obj);
builder_.DeoptCheck(isEcmaObject, frameState, DeoptType::ISNOTECMAOBJECT);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void MCRLowering::LowerIsDataViewCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef frameState = acc_.GetFrameState(gate);
GateRef obj = acc_.GetValueIn(gate, 0);
GateRef isDataView = builder_.CheckJSType(obj, JSType::JS_DATA_VIEW);
builder_.DeoptCheck(isDataView, frameState, DeoptType::ISNOTDATAVIEW);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void MCRLowering::LowerIsTaggedBooleanCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef frameState = acc_.GetFrameState(gate);
GateRef value = acc_.GetValueIn(gate, 0);
GateRef taggedIsBoolean = builder_.TaggedIsBoolean(value);
builder_.DeoptCheck(taggedIsBoolean, frameState, DeoptType::ISNOTTAGGEDBOOLEAN);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void MCRLowering::LowerValueCheckNegOverflow(GateRef gate)
{
Environment env(gate, circuit_, &builder_);

View File

@ -73,6 +73,9 @@ private:
void LowerLexVarIsHoleCheck(GateRef gate);
void LowerIsUndefinedOrHoleCheck(GateRef gate);
void LowerIsNotUndefinedOrHoleCheck(GateRef gate);
void LowerIsEcmaObjectCheck(GateRef gate);
void LowerIsDataViewCheck(GateRef gate);
void LowerIsTaggedBooleanCheck(GateRef gate);
void LowerStoreMemory(GateRef gate);
void LowerCheckNullAndConvert(GateRef gate, GateRef frameState);
void LowerUndefinedAndConvert(GateRef gate, GateRef frameState);

View File

@ -29,6 +29,9 @@ namespace panda::ecmascript::kungfu {
V(LexVarIsHoleCheck, LEX_VAR_IS_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(IsUndefinedOrHoleCheck, IS_UNDEFINED_OR_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(IsNotUndefinedOrHoleCheck, IS_NOT_UNDEFINED_OR_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(IsEcmaObjectCheck, IS_ECMA_OBJECT_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(IsDataViewCheck, IS_DATA_VIEW_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(IsTaggedBooleanCheck, IS_TAGGED_BOOLEAN_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(TaggedIsHeapObject, TAGGED_IS_HEAP_OBJECT, GateFlags::NO_WRITE, 1, 1, 1) \
V(IsMarkerCellValid, IS_MARKER_CELL_VALID, GateFlags::NO_WRITE, 1, 1, 1) \
V(StringEqual, STRING_EQUAL, GateFlags::NO_WRITE, 1, 1, 2)
@ -106,6 +109,9 @@ namespace panda::ecmascript::kungfu {
V(MathImul, MATH_IMUL, GateFlags::NO_WRITE, 1, 1, 2) \
V(GlobalIsFinite, GLOBAL_IS_FINITE, GateFlags::NO_WRITE, 1, 1, 1) \
V(GlobalIsNan, GLOBAL_IS_NAN, GateFlags::NO_WRITE, 1, 1, 1) \
V(ArrayBufferIsView, ARRAY_BUFFER_IS_VIEW, GateFlags::NO_WRITE, 1, 1, 1) \
V(DataViewGet, DATA_VIEW_GET, GateFlags::NO_WRITE, 1, 1, 5) \
V(DataViewSet, DATA_VIEW_SET, GateFlags::NO_WRITE, 1, 1, 6) \
MCR_BINARY_GATE_META_DATA_CACHE_LIST(V)
#define MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \

View File

@ -13,9 +13,12 @@
* limitations under the License.
*/
#include "ecmascript/compiler/native_inline_lowering.h"
#include "ecmascript/base/number_helper.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/circuit_builder_helper.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/js_dataview.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/message_string.h"
@ -179,6 +182,29 @@ void NativeInlineLowering::RunNativeInlineLowering()
case BuiltinsStubCSigns::ID::MathFloor:
TryInlineMathUnaryBuiltin(gate, argc, id, circuit_->MathFloor(), skipThis);
break;
case BuiltinsStubCSigns::ID::ArrayBufferIsView:
TryInlineArrayBufferIsView(gate, argc, id, skipThis);
break;
case BuiltinsStubCSigns::ID::DataViewGetFloat32:
case BuiltinsStubCSigns::ID::DataViewGetFloat64:
case BuiltinsStubCSigns::ID::DataViewGetInt8:
case BuiltinsStubCSigns::ID::DataViewGetInt16:
case BuiltinsStubCSigns::ID::DataViewGetInt32:
case BuiltinsStubCSigns::ID::DataViewGetUint16:
case BuiltinsStubCSigns::ID::DataViewGetUint32:
case BuiltinsStubCSigns::ID::DataViewGetUint8:
TryInlineDataViewGet(gate, argc, id);
break;
case BuiltinsStubCSigns::ID::DataViewSetFloat32:
case BuiltinsStubCSigns::ID::DataViewSetFloat64:
case BuiltinsStubCSigns::ID::DataViewSetInt8:
case BuiltinsStubCSigns::ID::DataViewSetInt16:
case BuiltinsStubCSigns::ID::DataViewSetInt32:
case BuiltinsStubCSigns::ID::DataViewSetUint8:
case BuiltinsStubCSigns::ID::DataViewSetUint16:
case BuiltinsStubCSigns::ID::DataViewSetUint32:
TryInlineDataViewSet(gate, argc, id);
break;
default:
break;
}
@ -357,4 +383,83 @@ void NativeInlineLowering::TryInlineMathMinMaxBuiltin(GateRef gate, size_t argc,
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
}
void NativeInlineLowering::TryInlineArrayBufferIsView(GateRef gate,
size_t argc,
BuiltinsStubCSigns::ID id,
bool skipThis)
{
if (!skipThis) {
return;
}
if (argc != 1) {
return;
}
CallThis1TypeInfoAccessor tacc(thread_, circuit_, gate);
Environment env(gate, circuit_, &builder_);
if (!Uncheck()) {
builder_.CallTargetCheck(gate, tacc.GetFunc(), builder_.IntPtr(static_cast<int64_t>(id)), {tacc.GetArg0()});
}
GateRef arg0 = tacc.GetArg0();
GateRef ret = builder_.ArrayBufferIsView(arg0);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
}
void NativeInlineLowering::TryInlineDataViewGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id)
{
if (argc != 1 && argc != 2) { // number of args must be 1/2
return;
}
Environment env(gate, circuit_, &builder_);
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
}
GateRef thisObj = acc_.GetValueIn(gate, 0); // 0: this
builder_.IsEcmaObjectCheck(thisObj);
builder_.IsDataViewCheck(thisObj);
GateRef dataViewCallID = builder_.Int32(id);
GateRef index = acc_.GetValueIn(gate, 1); // 1: index of dataView
GateRef ret = Circuit::NullGate();
GateRef frameState = acc_.GetFrameState(gate);
if (argc == 1) { // if not provide isLittleEndian, default use big endian
ret = builder_.DataViewGet(thisObj, index, dataViewCallID, builder_.TaggedFalse(), frameState);
} else if (argc == 2) { // 2: provide isLittleEndian
GateRef isLittleEndian = acc_.GetValueIn(gate, 2); // 2: is little endian mode
builder_.IsTaggedBooleanCheck(isLittleEndian);
ret = builder_.DataViewGet(thisObj, index, dataViewCallID, isLittleEndian, frameState);
}
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
}
void NativeInlineLowering::TryInlineDataViewSet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id)
{
if (argc != 1 && argc != 2 && argc != 3) { // number of args must be 1/2/3
return;
}
Environment env(gate, circuit_, &builder_);
if (!Uncheck()) {
builder_.CallTargetCheck(gate, acc_.GetValueIn(gate, argc + 1), builder_.IntPtr(static_cast<int64_t>(id)));
}
GateRef thisObj = acc_.GetValueIn(gate, 0); // 0: this
builder_.IsEcmaObjectCheck(thisObj);
builder_.IsDataViewCheck(thisObj);
GateRef dataViewCallID = builder_.Int32(id);
GateRef index = acc_.GetValueIn(gate, 1); // 1: index
GateRef ret = Circuit::NullGate();
GateRef frameState = acc_.GetFrameState(gate);
if (argc == 1) { // arg counts is 1
ret = builder_.DataViewSet(
thisObj, index, builder_.Double(base::NAN_VALUE), dataViewCallID, builder_.TaggedFalse(), frameState);
} else if (argc == 2) { // arg counts is 2
GateRef value = acc_.GetValueIn(gate, 2); // 2: value
ret = builder_.DataViewSet(thisObj, index, value, dataViewCallID, builder_.TaggedFalse(), frameState);
} else if (argc == 3) { // arg counts is 3
GateRef value = acc_.GetValueIn(gate, 2); // 2: value
GateRef isLittleEndian = acc_.GetValueIn(gate, 3); // 3: is little endian mode
builder_.IsTaggedBooleanCheck(isLittleEndian);
ret = builder_.DataViewSet(thisObj, index, value, dataViewCallID, isLittleEndian, frameState);
}
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), ret);
}
} // namespace panda::ecmascript

View File

@ -16,10 +16,14 @@
#ifndef ECMASCRIPT_COMPILER_BUILTIN_INLINE_H
#define ECMASCRIPT_COMPILER_BUILTIN_INLINE_H
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/gate_accessor.h"
#include "ecmascript/compiler/graph_linearizer.h"
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/compiler/type_info_accessors.h"
#include "ecmascript/js_dataview.h"
#include "ecmascript/ts_types/ts_manager.h"
namespace panda::ecmascript::kungfu {
@ -55,6 +59,9 @@ private:
void TryInlineMathMinMaxBuiltin(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, const GateMetaData* op,
double defaultValue, bool skipThis);
void TryInlineMathClz32Builtin(GateRef gate, size_t argc, bool skipThis);
void TryInlineArrayBufferIsView(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id, bool skipThis);
void TryInlineDataViewGet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id);
void TryInlineDataViewSet(GateRef gate, size_t argc, BuiltinsStubCSigns::ID id);
bool EnableLog() const
{

View File

@ -14,11 +14,17 @@
*/
#include "ecmascript/compiler/number_speculative_retype.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/number_gate_info.h"
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/compiler/share_opcodes.h"
#include "ecmascript/compiler/type.h"
#include <cstdint>
#include "ecmascript/compiler/variable_type.h"
namespace panda::ecmascript::kungfu {
GateRef NumberSpeculativeRetype::SetOutputType(GateRef gate, GateType gateType)
@ -216,6 +222,10 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
return VisitGlobalBuiltin<true>(gate);
case OpCode::MATH_IMUL:
return VisitMathImul(gate);
case OpCode::DATA_VIEW_GET:
return VisitDataViewGet(gate);
case OpCode::DATA_VIEW_SET:
return VisitDataViewSet(gate);
case OpCode::JS_BYTECODE:
case OpCode::RUNTIME_CALL:
case OpCode::PRIMITIVE_TYPE_CHECK:
@ -940,6 +950,38 @@ GateRef NumberSpeculativeRetype::TryConvertConstant(GateRef gate, bool needInt32
return Circuit::NullGate();
}
GateRef NumberSpeculativeRetype::TryConvertConstantToInt32(GateRef gate)
{
if (acc_.GetOpCode(gate) != OpCode::CONSTANT) {
return Circuit::NullGate();
}
if (acc_.GetGateType(gate).IsNJSValueType()) {
MachineType mType = acc_.GetMachineType(gate);
if (mType == MachineType::I32) {
int32_t rawValue = acc_.GetInt32FromConstant(gate);
return builder_.Int32(rawValue);
} else if (mType == MachineType::F64) {
double rawValue = acc_.GetFloat64FromConstant(gate);
int32_t int32Value = base::NumberHelper::DoubleInRangeInt32(rawValue);
return builder_.Int32(int32Value);
} else {
return Circuit::NullGate();
}
}
JSTaggedValue value(acc_.GetConstantValue(gate));
if (value.IsInt()) {
int32_t rawValue = value.GetInt();
return builder_.Int32(rawValue);
} else if (value.IsDouble()) {
double rawValue = value.GetDouble();
int32_t int32Value = base::NumberHelper::DoubleInRangeInt32(rawValue);
return builder_.Int32(int32Value);
}
return Circuit::NullGate();
}
GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support,
OpType type)
{
@ -1006,6 +1048,70 @@ GateRef NumberSpeculativeRetype::CheckAndConvertToInt32(GateRef gate, GateType g
return result;
}
GateRef NumberSpeculativeRetype::CheckBoundAndConvertToInt32(GateRef gate, ConvertSupport support, OpType type)
{
auto result = TryConvertConstantToInt32(gate);
GateType gateType = acc_.GetGateType(gate);
if (result != Circuit::NullGate()) {
acc_.DeleteGateIfNoUse(gate);
ResizeAndSetTypeInfo(result, TypeInfo::INT32);
return result;
}
TypeInfo output = GetOutputTypeInfo(gate);
switch (output) {
case TypeInfo::INT1:
result = builder_.ConvertBoolToInt32(gate, support);
break;
case TypeInfo::CHAR:
case TypeInfo::INT32:
return gate;
case TypeInfo::UINT32: {
result = builder_.CheckUInt32AndConvertToInt32(gate);
break;
}
case TypeInfo::FLOAT64: {
result = builder_.DoubleCheckINFInRangeInt32(gate);
break;
}
case TypeInfo::HOLE_INT:
result = builder_.CheckHoleIntAndConvertToInt32(gate);
break;
case TypeInfo::HOLE_DOUBLE:
result = builder_.CheckHoleDoubleAndConvertToInt32(gate);
break;
case TypeInfo::NONE:
case TypeInfo::TAGGED: {
if (gateType.IsIntType()) {
result = builder_.CheckTaggedIntAndConvertToInt32(gate);
} else if (gateType.IsDoubleType()) {
GateRef doubleValue = builder_.CheckTaggedDoubleAndConvertToFloat64(gate);
result = builder_.DoubleInRangeInt32(doubleValue);
} else if (gateType.IsNullType()) {
result = builder_.CheckNullAndConvertToInt32(gate);
} else if (gateType.IsBooleanType()) {
result = builder_.CheckTaggedBooleanAndConvertToInt32(gate);
} else if (gateType.IsUndefinedType()) {
if (type == OpType::SHIFT_AND_LOGICAL) {
result = builder_.CheckUndefinedAndConvertToInt32(gate);
} else {
LOG_ECMA(FATAL) << "undefined cannot convert to int type";
}
} else {
GateRef doubleValue = builder_.CheckTaggedNumberAndConvertToFloat64(gate);
result = builder_.DoubleInRangeInt32(doubleValue);
}
break;
}
default: {
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
return Circuit::NullGate();
}
}
ResizeAndSetTypeInfo(result, TypeInfo::INT32);
return result;
}
GateRef NumberSpeculativeRetype::CheckAndConvertToFloat64(GateRef gate, GateType gateType,
ConvertToNumber convert)
{
@ -1047,7 +1153,6 @@ GateRef NumberSpeculativeRetype::CheckAndConvertToFloat64(GateRef gate, GateType
} else if (gateType.IsUndefinedType()) {
result = builder_.CheckUndefinedAndConvertToFloat64(gate);
} else {
ASSERT(gateType.IsNumberType());
if (convert == ConvertToNumber::ALL) {
GateRef glue = acc_.GetGlueFromArgList();
GateRef number = builder_.ToNumber(glue, gate, glue);
@ -1614,7 +1719,60 @@ GateRef NumberSpeculativeRetype::VisitMathImul(GateRef gate)
acc_.SetGateType(gate, GateType::NJSValue());
acc_.SetMachineType(gate, MachineType::I32);
acc_.ReplaceStateIn(gate, builder_.GetState());
acc_.ReplaceDependIn(gate, builder_.GetDepend());
return Circuit::NullGate();
}
GateRef NumberSpeculativeRetype::VisitDataViewGet(GateRef gate)
{
GateRef builtinsID = acc_.GetValueIn(gate, 2);
auto ID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(builtinsID));
if (IsRetype()) {
switch (ID) {
case BuiltinsStubCSigns::ID::DataViewGetInt8:
return SetOutputType(gate, GateType::IntType());
case BuiltinsStubCSigns::ID::DataViewGetUint8:
return SetOutputType(gate, GateType::IntType());
case BuiltinsStubCSigns::ID::DataViewGetInt16:
return SetOutputType(gate, GateType::IntType());
case BuiltinsStubCSigns::ID::DataViewGetUint16:
return SetOutputType(gate, GateType::IntType());
case BuiltinsStubCSigns::ID::DataViewGetInt32:
return SetOutputType(gate, GateType::IntType());
case BuiltinsStubCSigns::ID::DataViewGetUint32:
return SetOutputType(gate, TypeInfo::UINT32);
case BuiltinsStubCSigns::ID::DataViewGetFloat32:
return SetOutputType(gate, GateType::DoubleType());
case BuiltinsStubCSigns::ID::DataViewGetFloat64:
return SetOutputType(gate, GateType::DoubleType());
default:
UNREACHABLE();
}
}
ASSERT(IsConvert());
Environment env(gate, circuit_, &builder_);
GateRef index = acc_.GetValueIn(gate, 1);
GateRef input = CheckBoundAndConvertToInt32(index, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
acc_.ReplaceValueIn(gate, input, 1);
acc_.ReplaceStateIn(gate, builder_.GetState());
acc_.ReplaceDependIn(gate, builder_.GetDepend());
return Circuit::NullGate();
}
GateRef NumberSpeculativeRetype::VisitDataViewSet(GateRef gate)
{
if (IsRetype()) {
return SetOutputType(gate, GateType::UndefinedType());
}
ASSERT(IsConvert());
Environment env(gate, circuit_, &builder_);
GateRef index = acc_.GetValueIn(gate, 1);
GateRef inputIndex = CheckBoundAndConvertToInt32(index, ConvertSupport::ENABLE, OpType::SHIFT_AND_LOGICAL);
GateRef value = acc_.GetValueIn(gate, 2);
GateRef inputValue = CheckAndConvertToFloat64(value, acc_.GetGateType(value), ConvertToNumber::BOOL_ONLY);
acc_.ReplaceValueIn(gate, inputIndex, 1); // replace index of dataview to Int32
acc_.ReplaceValueIn(gate, inputValue, 2); // replace input value to Double64
acc_.ReplaceStateIn(gate, builder_.GetState());
acc_.ReplaceDependIn(gate, builder_.GetDepend());
return Circuit::NullGate();

View File

@ -108,6 +108,9 @@ private:
GateRef VisitStoreProperty(GateRef gate);
GateRef VisitLoadProperty(GateRef gate);
GateRef VisitNumberRelated(GateRef gate);
GateRef VisitCallBuiltins(GateRef gate);
GateRef VisitDataViewGet(GateRef gate);
GateRef VisitDataViewSet(GateRef gate);
GateRef VisitOthers(GateRef gate);
GateRef VisitTypeConvert(GateRef gate);
GateRef VisitFrameState(GateRef gate);
@ -134,12 +137,16 @@ private:
GateRef CheckAndConvertToInt32(GateRef gate, GateType gateType, ConvertSupport support = ConvertSupport::ENABLE,
OpType type = OpType::NORMAL);
GateRef CheckBoundAndConvertToInt32(GateRef gate,
ConvertSupport support = ConvertSupport::ENABLE,
OpType type = OpType::NORMAL);
GateRef CheckAndConvertToFloat64(GateRef gate, GateType gateType,
ConvertToNumber convert = ConvertToNumber::BOOL_ONLY);
GateRef CheckAndConvertToTagged(GateRef gate, GateType gateType, ConvertToNumber convert);
GateRef CheckAndConvertToBool(GateRef gate, GateType gateType);
GateRef ConvertToTagged(GateRef gate);
GateRef TryConvertConstant(GateRef gate, bool needInt32);
GateRef TryConvertConstantToInt32(GateRef gate);
GateRef ConvertTaggedToNJSValue(GateRef gate, TypeInfo output);
TypeInfo GetOuputForPhi(GateRef gate, bool ignoreConstant);

View File

@ -114,6 +114,12 @@ enum class TypedCallTargetCheckOp : uint8_t;
V(IsNotUndefinedOrHole, ISNOTUNDEFINEDORHOLE) \
V(BuiltinInliningTypeGuard, BUILTIN_INLINING_TYPE_GUARD) \
V(OsrLoopExit, OSRLOOPEXIT) \
V(IsNotEcmaObject, ISNOTECMAOBJECT) \
V(IsNotDataView, ISNOTDATAVIEW) \
V(IsNotTaggedBoolean, ISNOTTAGGEDBOOLEAN) \
V(IndexLessZeroOrInfinity, INDEXLESSZEROORINFINITY) \
V(ArrayBufferIsDetached, ARRAYBUFFERISDETACHED) \
V(TotalSizeOverflow, TOTALSIZEOVERFLOW)
enum class DeoptType : uint8_t {
NOTCHECK = 0,

View File

@ -136,7 +136,7 @@ namespace panda::ecmascript::kungfu {
MCR_GATE_OPCODE_LIST(V) \
HCR_GATE_OPCODE_LIST(V)
enum class OpCode : uint8_t {
enum class OpCode : uint16_t {
NOP = 0,
#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) OP,
IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE)

View File

@ -13,8 +13,26 @@
* limitations under the License.
*/
#include "ecmascript/compiler/typed_native_inline_lowering.h"
#include "ecmascript/compiler/circuit_builder_helper.h"
#include "ecmascript/base/number_helper.h"
#include "ecmascript/builtins/builtins_errors.h"
#include "ecmascript/byte_array.h"
#include "ecmascript/compiler/assembler/assembler.h"
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/circuit_builder-inl.h"
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/circuit_builder_helper.h"
#include "ecmascript/compiler/gate.h"
#include "ecmascript/compiler/rt_call_signature.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/compiler/share_opcodes.h"
#include "ecmascript/compiler/variable_type.h"
#include "ecmascript/js_arraybuffer.h"
#include "ecmascript/js_dataview.h"
#include "ecmascript/js_hclass.h"
#include "ecmascript/js_native_pointer.h"
#include "ecmascript/message_string.h"
#include "macros.h"
namespace panda::ecmascript::kungfu {
GateRef TypedNativeInlineLowering::VisitGate(GateRef gate)
@ -151,6 +169,15 @@ GateRef TypedNativeInlineLowering::VisitGate(GateRef gate)
case OpCode::GLOBAL_IS_NAN:
LowerGlobalIsNan(gate);
break;
case OpCode::DATA_VIEW_GET:
LowerDataViewProtoFunc(gate, DataViewProtoFunc::GET);
break;
case OpCode::DATA_VIEW_SET:
LowerDataViewProtoFunc(gate, DataViewProtoFunc::SET);
break;
case OpCode::ARRAY_BUFFER_IS_VIEW:
LowerArrayBufferIsView(gate);
break;
default:
break;
}
@ -835,6 +862,461 @@ void TypedNativeInlineLowering::LowerMathSqrt(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), ret);
}
void TypedNativeInlineLowering::LowerArrayBufferIsView(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef arg = acc_.GetValueIn(gate, 0);
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.TaggedFalse());
Label exit(&builder_);
Label isDataViewOrTypedArray(&builder_);
Label returnTaggedTrue(&builder_);
BRANCH_CIR(builder_.IsEcmaObject(arg), &isDataViewOrTypedArray, &exit);
builder_.Bind(&isDataViewOrTypedArray);
{
GateRef isDataView = builder_.CheckJSType(arg, JSType::JS_DATA_VIEW);
GateRef isTypedArray = builder_.TaggedObjectIsTypedArray(arg);
BRANCH_CIR(builder_.BoolOr(isDataView, isTypedArray), &returnTaggedTrue, &exit);
}
builder_.Bind(&returnTaggedTrue);
{
result = builder_.TaggedTrue();
builder_.Jump(&exit);
}
builder_.Bind(&exit);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
}
void TypedNativeInlineLowering::LowerDataViewProtoFunc(GateRef gate, DataViewProtoFunc func)
{
Environment env(gate, circuit_, &builder_);
Label isNotDetachedBuffer(&builder_);
Label isNotByteArray(&builder_);
Label getPointFromByteArray(&builder_);
Label getPointFromNotByteArray(&builder_);
Label getValueFromBuffer(&builder_);
Label bufferByteLengthIsZero(&builder_);
Label bufferByteLengthIsNotZero(&builder_);
GateRef thisobj = acc_.GetValueIn(gate, 0);
GateRef requestIndex = acc_.GetValueIn(gate, 1); // 1: requestIndex
GateRef builtinId = Circuit::NullGate();
GateRef isLittleEndian = Circuit::NullGate();
GateRef frameState = Circuit::NullGate();
ASSERT(func == DataViewProtoFunc::GET || func == DataViewProtoFunc::SET);
if (func == DataViewProtoFunc::GET) {
builtinId = acc_.GetValueIn(gate, 2); // 2: builtinId
isLittleEndian = acc_.GetValueIn(gate, 3); // 3: isLittleEndian
frameState = acc_.GetValueIn(gate, 4); // 4: frameState
} else if (func == DataViewProtoFunc::SET) {
builtinId = acc_.GetValueIn(gate, 3); // 3: builtinId
isLittleEndian = acc_.GetValueIn(gate, 4); // 4: isLittleEndian
frameState = acc_.GetValueIn(gate, 5); // 5: frameState
} else {
UNREACHABLE();
}
GateRef resultfinal = Circuit::NullGate();
DEFVALUE(dataPointer, (&builder_), VariableType::NATIVE_POINTER(), builder_.IntPtr(0));
builder_.DeoptCheck(builder_.Int32UnsignedLessThan(requestIndex, builder_.Int32(INT32_MAX)),
frameState,
DeoptType::INDEXLESSZEROORINFINITY);
GateRef viewedArrayBufferOffset = builder_.IntPtr(JSDataView::VIEW_ARRAY_BUFFER_OFFSET);
GateRef buffer = builder_.Load(VariableType::JS_ANY(), thisobj, viewedArrayBufferOffset);
BRANCH_CIR(builder_.CheckJSType(buffer, JSType::BYTE_ARRAY), &isNotDetachedBuffer, &isNotByteArray);
builder_.Bind(&isNotByteArray);
{
GateRef dataOffset = builder_.IntPtr(JSArrayBuffer::DATA_OFFSET);
GateRef dataSlot = builder_.Load(VariableType::JS_ANY(), buffer, dataOffset);
builder_.DeoptCheck(builder_.TaggedIsNotNull(dataSlot), frameState, DeoptType::ARRAYBUFFERISDETACHED);
builder_.Jump(&isNotDetachedBuffer);
}
builder_.Bind(&isNotDetachedBuffer);
GateRef byteOffset = builder_.IntPtr(JSDataView::BYTE_OFFSET_OFFSET);
GateRef offset = builder_.Load(VariableType::INT32(), thisobj, byteOffset);
GateRef sizeOffset = builder_.IntPtr(JSDataView::BYTE_LENGTH_OFFSET);
GateRef size = builder_.Load(VariableType::INT32(), thisobj, sizeOffset);
GateRef elementSize = BuiltinIdToSize(builtinId);
GateRef totalSize = builder_.Int32Add(requestIndex, elementSize);
builder_.DeoptCheck(builder_.Int32LessThan(totalSize, size), frameState, DeoptType::TOTALSIZEOVERFLOW);
GateRef bufferIndex = builder_.Int32Add(requestIndex, offset);
BRANCH_CIR(builder_.CheckJSType(buffer, JSType::BYTE_ARRAY), &getPointFromByteArray, &getPointFromNotByteArray);
builder_.Bind(&getPointFromByteArray);
{
dataPointer = builder_.Load(VariableType::NATIVE_POINTER(), buffer, builder_.IntPtr(ByteArray::DATA_OFFSET));
builder_.Jump(&getValueFromBuffer);
}
builder_.Bind(&getPointFromNotByteArray);
{
GateRef arrayBufferByteLengthOffset = builder_.IntPtr(JSArrayBuffer::BYTE_LENGTH_OFFSET);
GateRef arrayBufferByteLength = builder_.Load(VariableType::INT32(), buffer, arrayBufferByteLengthOffset);
BRANCH_CIR(builder_.Int32Equal(arrayBufferByteLength, builder_.Int32(0)),
&bufferByteLengthIsZero,
&bufferByteLengthIsNotZero);
builder_.Bind(&bufferByteLengthIsZero);
{
dataPointer = builder_.IntPtr(0);
builder_.Jump(&getValueFromBuffer);
}
builder_.Bind(&bufferByteLengthIsNotZero);
{
GateRef bufferDataOffset = builder_.IntPtr(JSArrayBuffer::DATA_OFFSET);
GateRef data = builder_.Load(VariableType::JS_ANY(), buffer, bufferDataOffset);
GateRef externalPointerOffset = builder_.IntPtr(JSNativePointer::POINTER_OFFSET);
GateRef externalPointer = builder_.Load(VariableType::NATIVE_POINTER(), data, externalPointerOffset);
dataPointer = externalPointer;
builder_.Jump(&getValueFromBuffer);
}
}
builder_.Bind(&getValueFromBuffer);
ASSERT(func == DataViewProtoFunc::GET || func == DataViewProtoFunc::SET);
if (func == DataViewProtoFunc::GET) {
resultfinal = GetValueFromBuffer(bufferIndex, *dataPointer, isLittleEndian, builtinId);
} else if (func == DataViewProtoFunc::SET) {
GateRef value = acc_.GetValueIn(gate, 2); // 2: value
resultfinal =
SetValueInBuffer(bufferIndex, value, *dataPointer, isLittleEndian, builtinId, acc_.GetGlueFromArgList());
} else {
UNREACHABLE();
}
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), resultfinal);
}
GateRef TypedNativeInlineLowering::BuiltinIdToSize(GateRef ID)
{
auto builtinsID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(ID));
switch (builtinsID) {
case BuiltinsStubCSigns::ID::DataViewGetInt8:
case BuiltinsStubCSigns::ID::DataViewGetUint8:
case BuiltinsStubCSigns::ID::DataViewSetUint8:
case BuiltinsStubCSigns::ID::DataViewSetInt8:
return builder_.Int32(ElmentSize::BITS_8);
case BuiltinsStubCSigns::ID::DataViewGetInt16:
case BuiltinsStubCSigns::ID::DataViewGetUint16:
case BuiltinsStubCSigns::ID::DataViewSetInt16:
case BuiltinsStubCSigns::ID::DataViewSetUint16:
return builder_.Int32(ElmentSize::BITS_16);
case BuiltinsStubCSigns::ID::DataViewGetUint32:
case BuiltinsStubCSigns::ID::DataViewGetInt32:
case BuiltinsStubCSigns::ID::DataViewGetFloat32:
case BuiltinsStubCSigns::ID::DataViewSetUint32:
case BuiltinsStubCSigns::ID::DataViewSetInt32:
case BuiltinsStubCSigns::ID::DataViewSetFloat32:
return builder_.Int32(ElmentSize::BITS_32);
case BuiltinsStubCSigns::ID::DataViewGetFloat64:
case BuiltinsStubCSigns::ID::DataViewSetFloat64:
return builder_.Int32(ElmentSize::BITS_64);
default:
UNREACHABLE();
}
}
GateRef TypedNativeInlineLowering::GetValueFromBuffer(GateRef bufferIndex,
GateRef dataPointer,
GateRef isLittleEndian,
GateRef ID)
{
Label entry(&builder_);
builder_.SubCfgEntry(&entry);
Label exit(&builder_);
Label littleEndian(&builder_);
Label bigEndian(&builder_);
Label passResult(&builder_);
GateRef finalResult = builder_.NullConstant();
BuiltinsStubCSigns::ID builtinsID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(ID));
switch (builtinsID) {
case BuiltinsStubCSigns::ID::DataViewGetUint8: {
GateRef uint8Res = builder_.Load(VariableType::INT8(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
finalResult = builder_.ZExtInt8ToInt64(uint8Res);
builder_.Jump(&exit);
break;
}
case BuiltinsStubCSigns::ID::DataViewGetInt8: {
GateRef int8res = builder_.Load(VariableType::INT8(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
finalResult = builder_.SExtInt8ToInt64(int8res);
builder_.Jump(&exit);
break;
}
case BuiltinsStubCSigns::ID::DataViewGetUint16: {
DEFVALUE(tempRes, (&builder_), VariableType::INT32(), builder_.Int32(0));
GateRef uint16Res = builder_.Load(VariableType::INT16(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
BRANCH_CIR(builder_.TaggedIsFalse(isLittleEndian), &bigEndian, &littleEndian);
builder_.Bind(&littleEndian);
{
tempRes = builder_.ZExtInt16ToInt32(uint16Res);
builder_.Jump(&passResult);
}
builder_.Bind(&bigEndian);
{
GateRef bigEndianInt16 = builder_.Int16ToBigEndianInt16(uint16Res);
tempRes = builder_.ZExtInt16ToInt32(bigEndianInt16);
builder_.Jump(&passResult);
}
builder_.Bind(&passResult);
{
finalResult = *tempRes;
builder_.Jump(&exit);
}
break;
}
case BuiltinsStubCSigns::ID::DataViewGetInt16: {
DEFVALUE(tempRes, (&builder_), VariableType::INT16(), builder_.Int16(0));
GateRef int16Res = builder_.Load(VariableType::INT16(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
BRANCH_CIR(builder_.TaggedIsFalse(isLittleEndian), &bigEndian, &littleEndian);
builder_.Bind(&littleEndian);
{
tempRes = int16Res;
builder_.Jump(&passResult);
}
builder_.Bind(&bigEndian);
{
tempRes = builder_.Int16ToBigEndianInt16(int16Res);
builder_.Jump(&passResult);
}
builder_.Bind(&passResult);
{
finalResult = *tempRes;
builder_.Jump(&exit);
}
break;
}
case BuiltinsStubCSigns::ID::DataViewGetUint32: {
DEFVALUE(tempRes, (&builder_), VariableType::INT32(), builder_.Int32(0));
GateRef uint32Res = builder_.Load(VariableType::INT32(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
BRANCH_CIR(builder_.TaggedIsFalse(isLittleEndian), &bigEndian, &littleEndian);
builder_.Bind(&littleEndian);
{
tempRes = uint32Res;
builder_.Jump(&passResult);
}
builder_.Bind(&bigEndian);
{
tempRes = builder_.Int32ToBigEndianInt32(uint32Res);
builder_.Jump(&passResult);
}
builder_.Bind(&passResult);
{
finalResult = *tempRes;
builder_.Jump(&exit);
}
break;
}
case BuiltinsStubCSigns::ID::DataViewGetInt32: {
DEFVALUE(tempRes, (&builder_), VariableType::INT32(), builder_.Int32(0));
GateRef int32Res = builder_.Load(VariableType::INT32(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
BRANCH_CIR(builder_.TaggedIsFalse(isLittleEndian), &bigEndian, &littleEndian);
builder_.Bind(&littleEndian);
{
tempRes = int32Res;
builder_.Jump(&passResult);
}
builder_.Bind(&bigEndian);
{
tempRes = builder_.Int32ToBigEndianInt32(int32Res);
builder_.Jump(&passResult);
}
builder_.Bind(&passResult);
{
finalResult = *tempRes;
builder_.Jump(&exit);
}
break;
}
case BuiltinsStubCSigns::ID::DataViewGetFloat32: {
DEFVALUE(tempRes, (&builder_), VariableType::FLOAT64(), builder_.Double(base::NAN_VALUE));
Label notNaN(&builder_);
GateRef int32Res = builder_.Load(VariableType::INT32(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
BRANCH_CIR(builder_.TaggedIsFalse(isLittleEndian), &bigEndian, &littleEndian);
builder_.Bind(&littleEndian);
{
GateRef float32Res = builder_.CastInt32ToFloat32(int32Res);
tempRes = builder_.ExtFloat32ToDouble(float32Res);
builder_.Jump(&passResult);
}
builder_.Bind(&bigEndian);
{
GateRef originFloat32Res = builder_.CastInt32ToFloat32(int32Res);
GateRef originDoubleRes = builder_.ExtFloat32ToDouble(originFloat32Res);
BRANCH_CIR(builder_.DoubleIsNAN(originDoubleRes), &passResult, &notNaN);
builder_.Bind(&notNaN);
{
GateRef bigEndianInt32Res = builder_.Int32ToBigEndianInt32(int32Res);
GateRef float32Res = builder_.CastInt32ToFloat32(bigEndianInt32Res);
tempRes = builder_.ExtFloat32ToDouble(float32Res);
builder_.Jump(&passResult);
}
}
builder_.Bind(&passResult);
{
finalResult = *tempRes;
builder_.Jump(&exit);
}
break;
}
case BuiltinsStubCSigns::ID::DataViewGetFloat64: {
DEFVALUE(tempRes, (&builder_), VariableType::FLOAT64(), builder_.Double(base::NAN_VALUE));
Label notNaN(&builder_);
GateRef int64Res = builder_.Load(VariableType::INT64(), dataPointer, builder_.ZExtInt32ToPtr(bufferIndex));
BRANCH_CIR(builder_.TaggedIsFalse(isLittleEndian), &bigEndian, &littleEndian);
builder_.Bind(&littleEndian);
{
tempRes = builder_.CastInt64ToFloat64(int64Res);
builder_.Jump(&passResult);
}
builder_.Bind(&bigEndian);
{
GateRef originFloat64Res = builder_.CastInt64ToFloat64(int64Res);
BRANCH_CIR(builder_.DoubleIsNAN(originFloat64Res), &passResult, &notNaN);
builder_.Bind(&notNaN);
{
GateRef bigEndianInt64Res = builder_.Int64ToBigEndianInt64(int64Res);
tempRes = builder_.CastInt64ToFloat64(bigEndianInt64Res);
builder_.Jump(&passResult);
}
}
builder_.Bind(&passResult);
{
finalResult = *tempRes;
builder_.Jump(&exit);
}
break;
}
default:
UNREACHABLE();
}
builder_.Bind(&exit);
builder_.SubCfgExit();
return finalResult;
}
GateRef TypedNativeInlineLowering::SetValueInBuffer(
GateRef bufferIndex, GateRef value, GateRef dataPointer, GateRef isLittleEndian, GateRef ID, GateRef glue)
{
Label entry(&builder_);
builder_.SubCfgEntry(&entry);
Label exit(&builder_);
Label littleEndian(&builder_);
Label bigEndian(&builder_);
Label passResult(&builder_);
GateRef offset = builder_.ZExtInt32ToPtr(bufferIndex);
GateRef int64Value = builder_.TruncFloatToInt64(value);
BuiltinsStubCSigns::ID builtinsID = static_cast<BuiltinsStubCSigns::ID>(acc_.GetConstantValue(ID));
switch (builtinsID) {
case BuiltinsStubCSigns::ID::DataViewSetUint8:
case BuiltinsStubCSigns::ID::DataViewSetInt8: {
GateRef int32Value = builder_.TruncInt64ToInt32(int64Value);
builder_.Store(VariableType::INT8(), glue, dataPointer, offset, builder_.TruncInt32ToInt8(int32Value));
builder_.Jump(&exit);
break;
}
case BuiltinsStubCSigns::ID::DataViewSetUint16:
case BuiltinsStubCSigns::ID::DataViewSetInt16: {
BRANCH_CIR(builder_.TaggedIsTrue(isLittleEndian), &littleEndian, &bigEndian);
builder_.Bind(&littleEndian);
{
builder_.Store(
VariableType::INT16(), glue, dataPointer, offset, builder_.TruncInt64ToInt16(int64Value));
builder_.Jump(&exit);
}
builder_.Bind(&bigEndian);
{
GateRef int16Value = builder_.TruncInt64ToInt16(int64Value);
GateRef bigEndianInt16 = builder_.Int16ToBigEndianInt16(int16Value);
builder_.Store(VariableType::INT16(), glue, dataPointer, offset, bigEndianInt16);
builder_.Jump(&exit);
}
break;
}
case BuiltinsStubCSigns::ID::DataViewSetFloat32: {
Label isNaN(&builder_);
Label notNaN(&builder_);
GateRef float32Value = builder_.TruncDoubleToFloat32(value);
BRANCH_CIR(builder_.DoubleIsNAN(value), &isNaN, &notNaN);
builder_.Bind(&isNaN);
{
builder_.Store(VariableType::FLOAT32(), glue, dataPointer, offset, float32Value);
builder_.Jump(&exit);
}
builder_.Bind(&notNaN);
{
BRANCH_CIR(builder_.TaggedIsTrue(isLittleEndian), &littleEndian, &bigEndian);
builder_.Bind(&littleEndian);
{
builder_.Store(VariableType::FLOAT32(), glue, dataPointer, offset, float32Value);
builder_.Jump(&exit);
}
builder_.Bind(&bigEndian);
{
GateRef int32Value = builder_.CaseFloat32ToInt32(float32Value);
GateRef bigEndianInt32Value = builder_.Int32ToBigEndianInt32(int32Value);
GateRef bigEndianFloat32Value = builder_.CastInt32ToFloat32(bigEndianInt32Value);
builder_.Store(VariableType::FLOAT32(), glue, dataPointer, offset, bigEndianFloat32Value);
builder_.Jump(&exit);
}
}
break;
}
case BuiltinsStubCSigns::ID::DataViewSetInt32:
case BuiltinsStubCSigns::ID::DataViewSetUint32: {
BRANCH_CIR(builder_.TaggedIsTrue(isLittleEndian), &littleEndian, &bigEndian);
builder_.Bind(&littleEndian);
{
builder_.Store(
VariableType::INT32(), glue, dataPointer, offset, builder_.TruncInt64ToInt32(int64Value));
builder_.Jump(&exit);
}
builder_.Bind(&bigEndian);
{
GateRef int32Value = builder_.TruncInt64ToInt32(int64Value);
GateRef bigEndianInt32 = builder_.Int32ToBigEndianInt32(int32Value);
builder_.Store(VariableType::INT32(), glue, dataPointer, offset, bigEndianInt32);
builder_.Jump(&exit);
}
break;
}
case BuiltinsStubCSigns::ID::DataViewSetFloat64: {
Label isNaN(&builder_);
Label notNaN(&builder_);
BRANCH_CIR(builder_.DoubleIsNAN(value), &isNaN, &notNaN);
{
builder_.Bind(&isNaN);
{
builder_.Store(VariableType::FLOAT64(), glue, dataPointer, offset, value);
builder_.Jump(&exit);
}
builder_.Bind(&notNaN);
{
BRANCH_CIR(builder_.TaggedIsTrue(isLittleEndian), &littleEndian, &bigEndian);
builder_.Bind(&littleEndian);
{
builder_.Store(VariableType::FLOAT64(), glue, dataPointer, offset, value);
builder_.Jump(&exit);
}
builder_.Bind(&bigEndian);
{
GateRef int64bitsValue = builder_.CastDoubleToInt64(value);
GateRef bigEndianInt64Value = builder_.Int64ToBigEndianInt64(int64bitsValue);
GateRef float64Value = builder_.CastInt64ToFloat64(bigEndianInt64Value);
builder_.Store(VariableType::FLOAT64(), glue, dataPointer, offset, float64Value);
builder_.Jump(&exit);
}
}
}
break;
}
default:
UNREACHABLE();
}
builder_.Bind(&exit);
builder_.SubCfgExit();
return builder_.UndefineConstant();
}
static void BuildMathSignDouble(Variable *resVarPtr, CircuitBuilder *builder, GateRef param,
std::vector<Label> *labelsForFloatCase)
{

View File

@ -16,9 +16,12 @@
#ifndef ECMASCRIPT_COMPILER_TYPED_NATIVE_INLINE_LOWERING_H
#define ECMASCRIPT_COMPILER_TYPED_NATIVE_INLINE_LOWERING_H
#include <cstdint>
#include "ecmascript/compiler/circuit.h"
#include "ecmascript/compiler/combined_pass_visitor.h"
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/compiler/variable_type.h"
namespace panda::ecmascript::kungfu {
class TypedNativeInlineLowering : public PassVisitor {
public:
@ -35,6 +38,10 @@ public:
~TypedNativeInlineLowering() = default;
GateRef VisitGate(GateRef gate) override;
private:
enum class DataViewProtoFunc : uint8_t { GET = 0, SET = 1 };
enum ElmentSize : uint32_t { BITS_8 = 1, BITS_16 = 2, BITS_32 = 4, BITS_64 = 8 };
void LowerGeneralUnaryMath(GateRef gate, RuntimeStubCSigns::ID stubId);
void LowerMathAtan2(GateRef gate);
void LowerTrunc(GateRef gate);
@ -54,6 +61,16 @@ private:
GateRef BuildRounding(GateRef gate, GateRef value, OpCode op);
void LowerTaggedRounding(GateRef gate);
void LowerDoubleRounding(GateRef gate);
void LowerArrayBufferIsView(GateRef gate);
void LowerDataViewProtoFunc(GateRef gate, DataViewProtoFunc proto);
GateRef BuiltinIdToSize(GateRef ID);
GateRef GetValueFromBuffer(GateRef bufferIndex, GateRef dataPointer, GateRef isLittleEndian, GateRef builtinId);
GateRef SetValueInBuffer(GateRef bufferIndex,
GateRef value,
GateRef dataPointer,
GateRef isLittleEndian,
GateRef builtinId,
GateRef glue);
GateRef BuildIntAbs(GateRef value);
GateRef BuildDoubleAbs(GateRef value);

View File

@ -76,10 +76,11 @@ inline uintptr_t GlobalEnvConstants::GetGlobalConstantAddr(ConstantIndex index)
SHARED_GLOBAL_ENV_CONSTANT_STRING(DECL_GET_IMPL_STRING) // NOLINT(readability-const-return-type)
SHARED_GLOBAL_ENV_CONSTANT_ACCESSOR(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
SHARED_GLOBAL_ENV_CONSTANT_SPECIAL(DECL_GET_IMPL_WITH_TYPE); // NOLINT(readability-const-return-type)
GLOBAL_ENV_CONSTANT_CLASS(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
GLOBAL_ENV_CONSTANT_SPECIAL(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
GLOBAL_ENV_CONSTANT_CONSTANT(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
GLOBAL_ENV_CACHES(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
GLOBAL_ENV_CONSTANT_CLASS(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
GLOBAL_ENV_CONSTANT_SPECIAL(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
GLOBAL_ENV_INLINED_BUILTINS(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
GLOBAL_ENV_CONSTANT_CONSTANT(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
GLOBAL_ENV_CACHES(DECL_GET_IMPL_WITH_TYPE) // NOLINT(readability-const-return-type)
#undef DECL_GET_IMPL_WITH_TYPE
#undef DECL_GET_IMPL_STRING
#undef DECL_GET_IMPL_COMMON

View File

@ -153,7 +153,10 @@ class ObjectFactory;
V(JSTaggedValue, EmptyLayoutInfo, EMPTY_LAYOUT_INFO_OBJECT_INDEX, ecma_roots_special) \
V(JSTaggedValue, DefaultSupers, DEFAULT_SUPERS_INDEX, ecma_roots_special) \
V(JSTaggedValue, EmptyTaggedQueue, EMPTY_TAGGED_QUEUE_OBJECT_INDEX, ecma_roots_special) \
V(JSTaggedValue, UndefinedCompletionRecord, UNDEFINED_COMPLRTION_RECORD_INDEX, ecma_roots_special) \
V(JSTaggedValue, UndefinedCompletionRecord, UNDEFINED_COMPLRTION_RECORD_INDEX, ecma_roots_special)
// Use for builtins inlining
#define GLOBAL_ENV_INLINED_BUILTINS(V) \
V(JSTaggedValue, MathSqrt, MATH_SQRT_INDEX, ecma_roots_special) \
V(JSTaggedValue, MathAcos, MATH_ACOS_INDEX, ecma_roots_special) \
V(JSTaggedValue, MathAcosh, MATH_ACOSH_INDEX, ecma_roots_special) \
@ -197,7 +200,24 @@ class ObjectFactory;
V(JSTaggedValue, StringIteratorProtoNext, STRING_ITERATOR_PROTO_NEXT_INDEX, ecma_roots_special) \
V(JSTaggedValue, ArrayIteratorProtoNext, ARRAY_ITERATOR_PROTO_NEXT_INDEX, ecma_roots_special) \
V(JSTaggedValue, IteratorProtoReturn, ITERATOR_PROTO_RETURN_INDEX, ecma_roots_special) \
V(JSTaggedValue, StringFromCharCode, STRING_FROM_CHAR_CODE_INDEX, ecma_roots_special)
V(JSTaggedValue, StringFromCharCode, STRING_FROM_CHAR_CODE_INDEX, ecma_roots_special) \
V(JSTaggedValue, ArrayBufferIsView, ARRAY_BUFFER_IS_VIEW_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewGetFloat32, DATA_VIEW_GET_FLOAT32_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewGetFloat64, DATA_VIEW_GET_FLOAT64_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewGetInt8, DATA_VIEW_GET_INT8_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewGetInt16, DATA_VIEW_GET_INT16_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewGetInt32, DATA_VIEW_GET_INT32_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewGetUint16, DATA_VIEW_GET_UINT16_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewGetUint32, DATA_VIEW_GET_UINT32_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewGetUint8, DATA_VIEW_GET_UINT8_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewSetFloat32, DATA_VIEW_SET_FLOAT32_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewSetFloat64, DATA_VIEW_SET_FLOAT64_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewSetInt8, DATA_VIEW_SET_INT8_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewSetInt16, DATA_VIEW_SET_INT16_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewSetInt32, DATA_VIEW_SET_INT32_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewSetUint8, DATA_VIEW_SET_UINT8_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewSetUint16, DATA_VIEW_SET_UINT16_INDEX, ecma_roots_special) \
V(JSTaggedValue, DataViewSetUint32, DATA_VIEW_SET_UINT32_INDEX, ecma_roots_special)
// All of type JSTaggedValue
#define SHARED_GLOBAL_ENV_CONSTANT_STRING(V) \
@ -567,6 +587,7 @@ enum class ConstantIndex : size_t {
SHARED_GLOBAL_ENV_CONSTANT_SPECIAL(INDEX_FILTER_WITH_TYPE)
GLOBAL_ENV_CONSTANT_CLASS(INDEX_FILTER_WITH_TYPE)
GLOBAL_ENV_CONSTANT_SPECIAL(INDEX_FILTER_WITH_TYPE)
GLOBAL_ENV_INLINED_BUILTINS(INDEX_FILTER_WITH_TYPE)
GLOBAL_ENV_CONSTANT_CONSTANT(INDEX_FILTER_WITH_TYPE)
GLOBAL_ENV_CACHES(INDEX_FILTER_WITH_TYPE)
#undef INDEX_FILTER_STRING
@ -634,6 +655,7 @@ public:
SHARED_GLOBAL_ENV_CONSTANT_SPECIAL(DECL_GET_WITH_TYPE)
GLOBAL_ENV_CONSTANT_CLASS(DECL_GET_WITH_TYPE)
GLOBAL_ENV_CONSTANT_SPECIAL(DECL_GET_WITH_TYPE)
GLOBAL_ENV_INLINED_BUILTINS(DECL_GET_WITH_TYPE)
GLOBAL_ENV_CONSTANT_CONSTANT(DECL_GET_WITH_TYPE)
GLOBAL_ENV_CACHES(DECL_GET_WITH_TYPE)
#undef DECL_GET_STRING

View File

@ -320,6 +320,7 @@
panda::ecmascript::TypeLiteralExtractor::TypeLiteralExtractor*;
panda::ecmascript::Unlink*;
panda::ecmascript::base::utf_helper::ConvertRegionUtf16ToUtf8*;
panda::ecmascript::base::NumberHelper::DoubleInRangeInt32*;
panda::ecmascript::kungfu::AOTSnapshot::StoreConstantPoolInfo*;
panda::ecmascript::kungfu::ArkStackMapBuilder::Collect*;
panda::ecmascript::kungfu::ArkStackMapBuilder::GenerateArkStackMap*;