Files
getingke 9ccd71388b fixed for review comment by wuzhefeng
Signed-off-by: getingke <getingke@huawei.com>
Change-Id: I2f0c61448663bd45f097210dcfe8fc37e4d92f07
2022-07-06 18:40:34 +08:00

524 lines
19 KiB
C++

/*
* Copyright (c) 2021 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 "common_stubs.h"
#include "ecmascript/base/number_helper.h"
#include "ecmascript/compiler/llvm_ir_builder.h"
#include "ecmascript/compiler/variable_type.h"
#include "ecmascript/js_array.h"
#include "ecmascript/message_string.h"
#include "ecmascript/tagged_hash_table.h"
#include "stub-inl.h"
namespace panda::ecmascript::kungfu {
using namespace panda::ecmascript;
#ifndef NDEBUG
void MulGCTestStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
auto env = GetEnvironment();
GateRef glue = PtrArgument(0);
GateRef x = Int64Argument(1);
GateRef y = Int64Argument(2); // 2: 3rd argument
DEFVARIABLE(intX, VariableType::INT64(), Int64(0));
DEFVARIABLE(intY, VariableType::INT64(), Int64(0));
DEFVARIABLE(valuePtr, VariableType::INT64(), Int64(0));
DEFVARIABLE(doubleX, VariableType::FLOAT64(), Double(0));
DEFVARIABLE(doubleY, VariableType::FLOAT64(), Double(0));
Label xIsNumber(env);
Label xNotNumberOryNotNumber(env);
Label xIsNumberAndyIsNumber(env);
Label xIsDoubleAndyIsDouble(env);
Branch(TaggedIsNumber(x), &xIsNumber, &xNotNumberOryNotNumber);
Bind(&xIsNumber);
{
Label yIsNumber(env);
// if right.IsNumber()
Branch(TaggedIsNumber(y), &yIsNumber, &xNotNumberOryNotNumber);
Bind(&yIsNumber);
{
Label xIsInt(env);
Label xNotInt(env);
Branch(TaggedIsInt(x), &xIsInt, &xNotInt);
Bind(&xIsInt);
{
intX = TaggedCastToInt64(x);
doubleX = CastInt64ToFloat64(*intX);
Jump(&xIsNumberAndyIsNumber);
}
Bind(&xNotInt);
{
doubleX = TaggedCastToDouble(x);
Jump(&xIsNumberAndyIsNumber);
}
}
}
Bind(&xNotNumberOryNotNumber);
Return(Hole(VariableType::JS_ANY()));
Label yIsInt(env);
Label yNotInt(env);
Bind(&xIsNumberAndyIsNumber);
{
Branch(TaggedIsInt(y), &yIsInt, &yNotInt);
Bind(&yIsInt);
{
intY = TaggedCastToInt64(y);
doubleY = CastInt64ToFloat64(*intY);
Jump(&xIsDoubleAndyIsDouble);
}
Bind(&yNotInt);
{
doubleY = TaggedCastToDouble(y);
Jump(&xIsDoubleAndyIsDouble);
}
}
Bind(&xIsDoubleAndyIsDouble);
doubleX = DoubleMul(*doubleX, *doubleY);
GateRef ptr1 = CallRuntime(glue, RTSTUB_ID(GetTaggedArrayPtrTest), {Int64(JSTaggedValue::VALUE_UNDEFINED)});
GateRef ptr2 = CallRuntime(glue, RTSTUB_ID(GetTaggedArrayPtrTest), {ptr1});
auto value1 = GetValueFromTaggedArray(VariableType::INT64(), ptr1, Int32(0));
GateRef tmp = CastInt64ToFloat64(value1);
doubleX = DoubleMul(*doubleX, tmp);
auto value2 = GetValueFromTaggedArray(VariableType::INT64(), ptr2, Int32(1));
tmp = CastInt64ToFloat64(value2);
doubleX = DoubleMul(*doubleX, tmp);
Return(DoubleBuildTaggedWithNoGC(*doubleX));
}
#endif
void AddStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
(void)glue;
GateRef x = TaggedArgument(1);
GateRef y = TaggedArgument(2);
Return(FastAdd(x, y));
}
void SubStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
(void)glue;
GateRef x = TaggedArgument(1);
GateRef y = TaggedArgument(2);
Return(FastSub(x, y));
}
void MulStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
(void)glue;
GateRef x = TaggedArgument(1);
GateRef y = TaggedArgument(2);
Return(FastMul(x, y));
}
void DivStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
(void)glue;
GateRef x = TaggedArgument(1);
GateRef y = TaggedArgument(2);
Return(FastDiv(x, y));
}
void ModStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef x = TaggedArgument(1);
GateRef y = TaggedArgument(2); // 2: 3rd argument
Return(FastMod(glue, x, y));
}
void TypeOfStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef obj = TaggedArgument(1);
Return(FastTypeOf(glue, obj));
}
void EqualStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
(void)glue;
GateRef x = TaggedArgument(1);
GateRef y = TaggedArgument(2);
Return(FastEqual(x, y));
}
void GetPropertyByIndexStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
Return(GetPropertyByIndex(glue, receiver, index));
}
void SetPropertyByIndexStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
Return(SetPropertyByIndex(glue, receiver, index, value, false));
}
void SetPropertyByIndexWithOwnStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef index = Int32Argument(2); /* 2 : 3rd parameter is index */
GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
Return(SetPropertyByIndex(glue, receiver, index, value, true));
}
void GetPropertyByNameStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef key = TaggedArgument(2); // 2 : 3rd para
Return(GetPropertyByName(glue, receiver, key));
}
void SetPropertyByNameStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef key = TaggedArgument(2); // 2 : 3rd para
GateRef value = TaggedArgument(3); // 3 : 4th para
Return(SetPropertyByName(glue, receiver, key, value, false));
}
void SetPropertyByNameWithOwnStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef key = TaggedArgument(2); // 2 : 3rd para
GateRef value = TaggedArgument(3); // 3 : 4th para
Return(SetPropertyByName(glue, receiver, key, value, true));
}
void GetPropertyByValueStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef key = TaggedArgument(2); // 2 : 3rd para
Return(GetPropertyByValue(glue, receiver, key));
}
void SetPropertyByValueStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is key */
GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
Return(SetPropertyByValue(glue, receiver, key, value, false));
}
void SetPropertyByValueWithOwnStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is key */
GateRef value = TaggedArgument(3); /* 3 : 4th parameter is value */
Return(SetPropertyByValue(glue, receiver, key, value, true));
}
void TryLoadICByNameStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
auto env = GetEnvironment();
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
Label receiverIsHeapObject(env);
Label receiverNotHeapObject(env);
Label hclassEqualFirstValue(env);
Label hclassNotEqualFirstValue(env);
Label cachedHandlerNotHole(env);
Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
Bind(&receiverIsHeapObject);
{
GateRef hclass = LoadHClass(receiver);
Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
&hclassEqualFirstValue, &hclassNotEqualFirstValue);
Bind(&hclassEqualFirstValue);
{
Return(LoadICWithHandler(glue, receiver, receiver, secondValue));
}
Bind(&hclassNotEqualFirstValue);
{
GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
Bind(&cachedHandlerNotHole);
{
Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
}
}
}
Bind(&receiverNotHeapObject);
{
Return(Hole());
}
}
void TryLoadICByValueStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
auto env = GetEnvironment();
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
Label receiverIsHeapObject(env);
Label receiverNotHeapObject(env);
Label hclassEqualFirstValue(env);
Label hclassNotEqualFirstValue(env);
Label firstValueEqualKey(env);
Label cachedHandlerNotHole(env);
Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
Bind(&receiverIsHeapObject);
{
GateRef hclass = LoadHClass(receiver);
Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
&hclassEqualFirstValue, &hclassNotEqualFirstValue);
Bind(&hclassEqualFirstValue);
Return(LoadElement(receiver, key));
Bind(&hclassNotEqualFirstValue);
{
Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
Bind(&firstValueEqualKey);
{
auto cachedHandler = CheckPolyHClass(secondValue, hclass);
Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
Bind(&cachedHandlerNotHole);
Return(LoadICWithHandler(glue, receiver, receiver, cachedHandler));
}
}
}
Bind(&receiverNotHeapObject);
Return(Hole());
}
void TryStoreICByNameStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
auto env = GetEnvironment();
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef firstValue = TaggedArgument(2); /* 2 : 3rd parameter is value */
GateRef secondValue = TaggedArgument(3); /* 3 : 4th parameter is value */
GateRef value = TaggedArgument(4); /* 4 : 5th parameter is value */
Label receiverIsHeapObject(env);
Label receiverNotHeapObject(env);
Label hclassEqualFirstValue(env);
Label hclassNotEqualFirstValue(env);
Label cachedHandlerNotHole(env);
Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
Bind(&receiverIsHeapObject);
{
GateRef hclass = LoadHClass(receiver);
Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
&hclassEqualFirstValue, &hclassNotEqualFirstValue);
Bind(&hclassEqualFirstValue);
{
Return(StoreICWithHandler(glue, receiver, receiver, value, secondValue));
}
Bind(&hclassNotEqualFirstValue);
{
GateRef cachedHandler = CheckPolyHClass(firstValue, hclass);
Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
Bind(&cachedHandlerNotHole);
{
Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
}
}
}
Bind(&receiverNotHeapObject);
Return(Hole(VariableType::INT64()));
}
void TryStoreICByValueStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
auto env = GetEnvironment();
GateRef glue = PtrArgument(0);
GateRef receiver = TaggedArgument(1);
GateRef key = TaggedArgument(2); /* 2 : 3rd parameter is value */
GateRef firstValue = TaggedArgument(3); /* 3 : 4th parameter is value */
GateRef secondValue = TaggedArgument(4); /* 4 : 5th parameter is value */
GateRef value = TaggedArgument(5); /* 5 : 6th parameter is value */
Label receiverIsHeapObject(env);
Label receiverNotHeapObject(env);
Label hclassEqualFirstValue(env);
Label hclassNotEqualFirstValue(env);
Label firstValueEqualKey(env);
Label cachedHandlerNotHole(env);
Branch(TaggedIsHeapObject(receiver), &receiverIsHeapObject, &receiverNotHeapObject);
Bind(&receiverIsHeapObject);
{
GateRef hclass = LoadHClass(receiver);
Branch(Int64Equal(TaggedCastToWeakReferentUnChecked(firstValue), hclass),
&hclassEqualFirstValue, &hclassNotEqualFirstValue);
Bind(&hclassEqualFirstValue);
Return(ICStoreElement(glue, receiver, key, value, secondValue));
Bind(&hclassNotEqualFirstValue);
{
Branch(Int64Equal(firstValue, key), &firstValueEqualKey, &receiverNotHeapObject);
Bind(&firstValueEqualKey);
{
GateRef cachedHandler = CheckPolyHClass(secondValue, hclass);
Branch(TaggedIsHole(cachedHandler), &receiverNotHeapObject, &cachedHandlerNotHole);
Bind(&cachedHandlerNotHole);
Return(StoreICWithHandler(glue, receiver, receiver, value, cachedHandler));
}
}
}
Bind(&receiverNotHeapObject);
Return(Hole(VariableType::INT64()));
}
void SetValueWithBarrierStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
GateRef glue = PtrArgument(0);
GateRef obj = TaggedArgument(1);
GateRef offset = PtrArgument(2); // 2 : 3rd para
GateRef value = TaggedArgument(3); // 3 : 4th para
SetValueWithBarrier(glue, obj, offset, value);
Return();
}
void TestAbsoluteAddressRelocationStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
auto env = GetEnvironment();
GateRef a = Int64Argument(0);
GateRef b = Int64Argument(1);
Label start(env);
Jump(&start);
Bind(&start);
GateRef globalValueC = RelocatableData(0xabc);
GateRef globalValueD = RelocatableData(0xbcd);
GateRef dummyValueC = Load(VariableType::INT64(), globalValueC);
GateRef dummyValueD = Load(VariableType::INT64(), globalValueD);
// Load from same relocatable data twice to see if it breaks constant fold opt. Result shows it doesn't.
GateRef dummyValueC1 = Load(VariableType::INT64(), globalValueC);
GateRef result = Int64Add(a, Int64Add(b, Int64Add(dummyValueC, Int64Add(dummyValueD, dummyValueC1))));
Return(result);
}
void JsProxyCallInternalStub::GenerateCircuit(const CompilationConfig *cfg)
{
Stub::GenerateCircuit(cfg);
auto env = GetEnvironment();
Label exit(env);
Label isNull(env);
Label notNull(env);
Label isUndefined(env);
Label isNotUndefined(env);
GateRef glue = PtrArgument(0);
GateRef argc = Int64Argument(1);
GateRef proxy = TaggedPointerArgument(2); // callTarget
GateRef argv = PtrArgument(3);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
GateRef handler = GetHandlerFromJSProxy(proxy);
Branch(TaggedIsNull(handler), &isNull, &notNull);
Bind(&isNull);
{
ThrowTypeAndReturn(glue, GET_MESSAGE_STRING_ID(NonCallable), Exception());
}
Bind(&notNull);
{
GateRef target = GetTargetFromJSProxy(proxy);
GateRef globalConstOffset = IntPtr(JSThread::GlueData::GetGlobalConstOffset(env->Is32Bit()));
GateRef keyOffset = PtrAdd(globalConstOffset,
PtrMul(IntPtr(static_cast<int64_t>(ConstantIndex::APPLY_STRING_INDEX)),
IntPtr(sizeof(JSTaggedValue))));
GateRef key = Load(VariableType::JS_ANY(), glue, keyOffset);
GateRef method = CallNGCRuntime(glue, RTSTUB_ID(JSObjectGetMethod), {glue, handler, key});
ReturnExceptionIfAbruptCompletion(glue);
Branch(TaggedIsUndefined(method), &isUndefined, &isNotUndefined);
Bind(&isUndefined);
{
result = CallNGCRuntime(glue, RTSTUB_ID(JSProxyCallInternalWithArgV), {glue, argc, target, argv});
Return(*result);
}
Bind(&isNotUndefined);
{
GateRef arrHandle = CallRuntime(glue, RTSTUB_ID(CreateArrayFromList), argc, argv);
GateRef thisArg = Load(VariableType::JS_POINTER(), argv, IntPtr(2*sizeof(JSTaggedValue)));
GateRef numArgs = Int64(JSPROXY_NUM_ARGS + NUM_MANDATORY_JSFUNC_ARGS);
GateRef lexEnv = Load(VariableType::JS_POINTER(), method, IntPtr(JSFunction::LEXICAL_ENV_OFFSET));
result = CallNGCRuntime(glue, RTSTUB_ID(JSCall),
{glue, lexEnv, numArgs, method, Undefined(), handler, target, thisArg, arrHandle});
Jump(&exit);
}
}
Bind(&exit);
Return(*result);
}
CallSignature CommonStubCSigns::callSigns_[CommonStubCSigns::NUM_OF_STUBS];
void CommonStubCSigns::Initialize()
{
#define INIT_SIGNATURES(name, counter) \
name##CallSignature::Initialize(&callSigns_[name]); \
callSigns_[name].SetID(name); \
callSigns_[name].SetConstructor( \
[](void* ciruit) { \
return static_cast<void*>(new name##Stub(static_cast<Circuit*>(ciruit))); \
});
COMMON_STUB_ID_LIST(INIT_SIGNATURES)
#undef INIT_SIGNATURES
}
void CommonStubCSigns::GetCSigns(std::vector<const CallSignature*>& outCSigns)
{
for (size_t i = 0; i < NUM_OF_STUBS; i++) {
outCSigns.push_back(&callSigns_[i]);
}
}
} // namespace panda::ecmascript::kungfu