mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
TSAOT Test262 Bugfix
1. Add codeEntry when definefunc in Asm interpreter and Tsaot. 2. Fix bound function bugs in calling bridge. 3. Fix partialGC bug by clearing derived pointers before remarking. 4. Fix newobjdynrange implementation bug. 5. Fix GC bug by setting taggedvalue type for homeobject and constpool. Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5IOZQ Signed-off-by: xujie <xujie101@huawei.com> Change-Id: Ifa413fea75355d244e2590f13328e0d52d128ebe
This commit is contained in:
parent
b7c690acb1
commit
c80693a0fa
@ -462,7 +462,7 @@ void CircuitBuilder::SetResolvedToFunction(GateRef glue, GateRef function, GateR
|
||||
void CircuitBuilder::SetConstPoolToFunction(GateRef glue, GateRef function, GateRef value)
|
||||
{
|
||||
GateRef offset = IntPtr(JSFunction::CONSTANT_POOL_OFFSET);
|
||||
Store(VariableType::INT64(), glue, function, offset, value);
|
||||
Store(VariableType::JS_ANY(), glue, function, offset, value);
|
||||
}
|
||||
|
||||
void CircuitBuilder::SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value)
|
||||
@ -503,7 +503,7 @@ void CircuitBuilder::SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef
|
||||
void CircuitBuilder::SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value)
|
||||
{
|
||||
GateRef offset = IntPtr(JSFunction::HOME_OBJECT_OFFSET);
|
||||
Store(VariableType::INT64(), glue, function, offset, value);
|
||||
Store(VariableType::JS_ANY(), glue, function, offset, value);
|
||||
}
|
||||
|
||||
Environment::Environment(size_t arguments, CircuitBuilder *builder)
|
||||
|
@ -3177,8 +3177,6 @@ void SlowPathLowering::LowerDefineNCFuncDyn(GateRef gate, GateRef glue, GateRef
|
||||
GateRef result;
|
||||
DEFVAlUE(method, (&builder_), VariableType::JS_POINTER(),
|
||||
GetObjectFromConstPool(jsFunc, builder_.ZExtInt16ToInt32(methodId)));
|
||||
GateRef codeEntry =
|
||||
builder_.Load(VariableType::NATIVE_POINTER(), *method, builder_.IntPtr(JSFunctionBase::CODE_ENTRY_OFFSET));
|
||||
Label isResolved(&builder_);
|
||||
Label notResolved(&builder_);
|
||||
Label defaultLabel(&builder_);
|
||||
@ -3193,7 +3191,6 @@ void SlowPathLowering::LowerDefineNCFuncDyn(GateRef gate, GateRef glue, GateRef
|
||||
&exceptionExit, ¬Exception);
|
||||
builder_.Bind(¬Exception);
|
||||
{
|
||||
builder_.SetCodeEntryToFunction(glue, *method, codeEntry);
|
||||
builder_.SetConstPoolToFunction(glue, *method, GetConstPool(jsFunc));
|
||||
builder_.Jump(&defaultLabel);
|
||||
}
|
||||
|
@ -513,15 +513,14 @@ void OptimizedCall::JSProxyCallInternalWithArgV(ExtendedAssembler *assembler)
|
||||
__ Pushq(rcx);
|
||||
__ Addq(-1, rax);
|
||||
__ Jne(&lCopyArgument2);
|
||||
|
||||
}
|
||||
__ Bind(&lCopyBoundArgument);
|
||||
{
|
||||
// get bound target
|
||||
__ Mov(Operand(jsFuncReg, JSBoundFunction::BOUND_ARGUMENTS_OFFSET), rdx);
|
||||
// get bound length
|
||||
__ Mov(Operand(rdx, TaggedArray::LENGTH_OFFSET), rax);
|
||||
__ Addq(TaggedArray::DATA_OFFSET, rdx);
|
||||
}
|
||||
__ Bind(&lCopyBoundArgument);
|
||||
{
|
||||
__ Cmp(0, rax);
|
||||
__ Je(&lPushCallTarget);
|
||||
}
|
||||
@ -782,15 +781,15 @@ void OptimizedCall::JSCall(ExtendedAssembler *assembler)
|
||||
__ Pushq(rcx);
|
||||
__ Addq(-1, rax);
|
||||
__ Jne(&lCopyArgument2);
|
||||
}
|
||||
|
||||
__ Bind(&lCopyBoundArgument);
|
||||
{
|
||||
// get bound target
|
||||
__ Mov(Operand(jsFuncReg, JSBoundFunction::BOUND_ARGUMENTS_OFFSET), rdx);
|
||||
// get bound length
|
||||
__ Mov(Operand(rdx, TaggedArray::LENGTH_OFFSET), rax);
|
||||
__ Addq(TaggedArray::DATA_OFFSET, rdx);
|
||||
}
|
||||
__ Bind(&lCopyBoundArgument);
|
||||
{
|
||||
__ Cmp(0, rax);
|
||||
__ Je(&lPushCallTarget);
|
||||
}
|
||||
|
@ -98,170 +98,4 @@ void SlowRuntimeHelper::SaveFrameToContext(JSThread *thread, JSHandle<GeneratorC
|
||||
context->SetNRegs(nregs);
|
||||
context->SetBCOffset(frameHandler.GetBytecodeOffset());
|
||||
}
|
||||
|
||||
JSTaggedValue ConstructGeneric(JSThread *thread, JSHandle<JSFunction> ctor, JSHandle<JSTaggedValue> newTgt,
|
||||
JSHandle<JSTaggedValue> preArgs, uint32_t argsCount, uint32_t baseArgLocation)
|
||||
{
|
||||
if (!ctor->IsConstructor()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> obj(thread, JSTaggedValue::Undefined());
|
||||
if (ctor->IsBase()) {
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
obj = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(ctor, newTgt));
|
||||
}
|
||||
uint32_t preArgsSize = preArgs->IsUndefined() ? 0 : JSHandle<TaggedArray>::Cast(preArgs)->GetLength();
|
||||
const uint32_t size = preArgsSize + argsCount;
|
||||
CVector<JSTaggedType> values;
|
||||
values.reserve(size);
|
||||
|
||||
JSMethod *method = ctor->GetCallTarget();
|
||||
if (method == nullptr) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Undefined target", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
// Add the input parameter
|
||||
FrameHandler frameHandler(thread);
|
||||
// add preArgs when boundfunction is encountered
|
||||
if (preArgsSize > 0) {
|
||||
JSHandle<TaggedArray> tgaPreArgs = JSHandle<TaggedArray>::Cast(preArgs);
|
||||
for (uint32_t i = 0; i < preArgsSize; ++i) {
|
||||
JSTaggedValue value = tgaPreArgs->Get(i);
|
||||
values.emplace_back(value.GetRawData());
|
||||
}
|
||||
for (uint32_t i = 0; i < argsCount; ++i) {
|
||||
JSTaggedValue value = frameHandler.GetVRegValue(baseArgLocation + i);
|
||||
values.emplace_back(value.GetRawData());
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < argsCount; ++i) {
|
||||
JSTaggedValue value = frameHandler.GetVRegValue(baseArgLocation + i);
|
||||
values.emplace_back(value.GetRawData());
|
||||
}
|
||||
}
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(ctor), obj, newTgt, size);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(size, values.data());
|
||||
JSTaggedValue resultValue = EcmaInterpreter::Execute(info);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 9.3.2 [[Construct]] (argumentsList, newTarget)
|
||||
if (resultValue.IsECMAObject()) {
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
if (ctor->IsBase()) {
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
if (!resultValue.IsUndefined()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "function is non-constructor", JSTaggedValue::Exception());
|
||||
}
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue ConstructBoundFunction(JSThread *thread, JSHandle<JSBoundFunction> ctor, JSHandle<JSTaggedValue> newTgt,
|
||||
JSHandle<JSTaggedValue> preArgs, uint32_t argsCount, uint32_t baseArgLocation)
|
||||
{
|
||||
JSHandle<JSTaggedValue> target(thread, ctor->GetBoundTarget());
|
||||
ASSERT(target->IsConstructor());
|
||||
|
||||
JSHandle<TaggedArray> boundArgs(thread, ctor->GetBoundArguments());
|
||||
JSMutableHandle<JSTaggedValue> newPreArgs(thread, preArgs.GetTaggedValue());
|
||||
if (newPreArgs->IsUndefined()) {
|
||||
newPreArgs.Update(boundArgs.GetTaggedValue());
|
||||
} else {
|
||||
newPreArgs.Update(
|
||||
TaggedArray::Append(thread, boundArgs, JSHandle<TaggedArray>::Cast(preArgs)).GetTaggedValue());
|
||||
}
|
||||
JSMutableHandle<JSTaggedValue> newTargetMutable(thread, newTgt.GetTaggedValue());
|
||||
if (JSTaggedValue::SameValue(ctor.GetTaggedValue(), newTgt.GetTaggedValue())) {
|
||||
newTargetMutable.Update(target.GetTaggedValue());
|
||||
}
|
||||
return SlowRuntimeHelper::Construct(thread, target, newTargetMutable, newPreArgs, argsCount, baseArgLocation);
|
||||
}
|
||||
|
||||
JSTaggedValue ConstructProxy(JSThread *thread, JSHandle<JSProxy> ctor, JSHandle<JSTaggedValue> newTgt,
|
||||
JSHandle<JSTaggedValue> preArgs, uint32_t argsCount, uint32_t baseArgLocation)
|
||||
{
|
||||
// step 1 ~ 4 get ProxyHandler and ProxyTarget
|
||||
JSHandle<JSTaggedValue> handler(thread, ctor->GetHandler());
|
||||
if (handler->IsNull()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor: handler is null", JSTaggedValue::Exception());
|
||||
}
|
||||
ASSERT(handler->IsJSObject());
|
||||
JSHandle<JSTaggedValue> target(thread, ctor->GetTarget());
|
||||
|
||||
// 5.Let trap be GetMethod(handler, "construct").
|
||||
JSHandle<JSTaggedValue> key(thread->GlobalConstants()->GetHandledProxyConstructString());
|
||||
JSHandle<JSTaggedValue> method = JSObject::GetMethod(thread, handler, key);
|
||||
|
||||
// 6.ReturnIfAbrupt(trap).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 7.If trap is undefined, then
|
||||
// a.Assert: target has a [[Construct]] internal method.
|
||||
// b.Return Construct(target, argumentsList, newTarget).
|
||||
if (method->IsUndefined()) {
|
||||
ASSERT(target->IsConstructor());
|
||||
return SlowRuntimeHelper::Construct(thread, target, newTgt, preArgs, argsCount, baseArgLocation);
|
||||
}
|
||||
|
||||
// 8.Let argArray be CreateArrayFromList(argumentsList).
|
||||
uint32_t preArgsSize = preArgs->IsUndefined() ? 0 : JSHandle<TaggedArray>::Cast(preArgs)->GetLength();
|
||||
const uint32_t size = preArgsSize + argsCount;
|
||||
JSHandle<TaggedArray> args = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(size);
|
||||
if (preArgsSize > 0) {
|
||||
JSHandle<TaggedArray> tgaPreArgs = JSHandle<TaggedArray>::Cast(preArgs);
|
||||
for (uint32_t i = 0; i < preArgsSize; ++i) {
|
||||
JSTaggedValue value = tgaPreArgs->Get(i);
|
||||
args->Set(thread, i, value);
|
||||
}
|
||||
}
|
||||
FrameHandler frameHandler(thread);
|
||||
for (uint32_t i = 0; i < argsCount; ++i) {
|
||||
JSTaggedValue value = frameHandler.GetVRegValue(baseArgLocation + i);
|
||||
args->Set(thread, i + preArgsSize, value);
|
||||
}
|
||||
|
||||
// step 8 ~ 9 Call(trap, handler, «target, argArray, newTarget »).
|
||||
const int32_t argsLength = 3; // 3: «target, argArray, newTarget »
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, method, handler, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(target.GetTaggedValue(), args.GetTaggedValue(), newTgt.GetTaggedValue());
|
||||
JSTaggedValue newObjValue = JSFunction::Call(info);
|
||||
// 10.ReturnIfAbrupt(newObj).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 11.If Type(newObj) is not Object, throw a TypeError exception.
|
||||
if (!newObjValue.IsECMAObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "new object is not object", JSTaggedValue::Exception());
|
||||
}
|
||||
// 12.Return newObj.
|
||||
return newObjValue;
|
||||
}
|
||||
|
||||
JSTaggedValue SlowRuntimeHelper::Construct(JSThread *thread, JSHandle<JSTaggedValue> ctor,
|
||||
JSHandle<JSTaggedValue> newTarget, JSHandle<JSTaggedValue> preArgs,
|
||||
uint32_t argsCount, uint32_t baseArgLocation)
|
||||
{
|
||||
if (newTarget->IsUndefined()) {
|
||||
newTarget = ctor;
|
||||
}
|
||||
|
||||
if (!(newTarget->IsConstructor() && ctor->IsConstructor())) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
|
||||
}
|
||||
if (ctor->IsJSFunction()) {
|
||||
return ConstructGeneric(thread, JSHandle<JSFunction>::Cast(ctor), newTarget, preArgs, argsCount,
|
||||
baseArgLocation);
|
||||
}
|
||||
if (ctor->IsBoundFunction()) {
|
||||
return ConstructBoundFunction(thread, JSHandle<JSBoundFunction>::Cast(ctor), newTarget, preArgs, argsCount,
|
||||
baseArgLocation);
|
||||
}
|
||||
if (ctor->IsJSProxy()) {
|
||||
return ConstructProxy(thread, JSHandle<JSProxy>::Cast(ctor), newTarget, preArgs, argsCount, baseArgLocation);
|
||||
}
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor NonConstructor", JSTaggedValue::Exception());
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -28,9 +28,6 @@ public:
|
||||
static JSTaggedValue CallBoundFunction(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static void SaveFrameToContext(JSThread *thread, JSHandle<GeneratorContext> context);
|
||||
|
||||
static JSTaggedValue Construct(JSThread *thread, JSHandle<JSTaggedValue> ctor, JSHandle<JSTaggedValue> newTarget,
|
||||
JSHandle<JSTaggedValue> preArgs, uint32_t argsCount, uint32_t baseArgLocation);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
@ -327,7 +327,7 @@ void Heap::CollectGarbage(TriggerGCType gcType)
|
||||
size_t originalNewSpaceSize = activeSemiSpace_->GetHeapObjectSize();
|
||||
memController_->StartCalculationBeforeGC();
|
||||
StatisticHeapObject(gcType);
|
||||
|
||||
GetDerivedPointers()->clear();
|
||||
switch (gcType) {
|
||||
case TriggerGCType::YOUNG_GC:
|
||||
// Use partial GC for young generation.
|
||||
|
@ -1519,7 +1519,14 @@ JSTaggedValue RuntimeStubs::RuntimeNewObjDynRange(JSThread *thread, const JSHand
|
||||
const JSHandle<JSTaggedValue> &newTarget, uint16_t firstArgIdx, uint16_t length)
|
||||
{
|
||||
JSHandle<JSTaggedValue> preArgs(thread, JSTaggedValue::Undefined());
|
||||
auto tagged = SlowRuntimeHelper::Construct(thread, func, newTarget, preArgs, length, firstArgIdx);
|
||||
JSHandle<TaggedArray> args = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(length);
|
||||
FrameHandler frameHandler(thread);
|
||||
for (uint16_t i = 0; i < length; ++i) {
|
||||
JSTaggedValue value = frameHandler.GetVRegValue(firstArgIdx + i);
|
||||
args->Set(thread, i, value);
|
||||
}
|
||||
|
||||
auto tagged = RuntimeOptConstruct(thread, func, newTarget, preArgs, args);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
return tagged;
|
||||
}
|
||||
@ -1629,6 +1636,7 @@ JSTaggedValue RuntimeStubs::RuntimeDefineNCFuncDyn(JSThread *thread, JSFunction
|
||||
JSHandle<JSHClass> dynclass = JSHandle<JSHClass>::Cast(env->GetFunctionClassWithoutProto());
|
||||
JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(method, dynclass, FunctionKind::ARROW_FUNCTION);
|
||||
ASSERT_NO_ABRUPT_COMPLETION(thread);
|
||||
jsFunc->SetCodeEntry(func->GetCodeEntry());
|
||||
return jsFunc.GetTaggedValue();
|
||||
}
|
||||
|
||||
@ -1651,7 +1659,6 @@ JSTaggedValue RuntimeStubs::RuntimeDefineGeneratorFunc(JSThread *thread, JSFunct
|
||||
ASSERT_NO_ABRUPT_COMPLETION(thread);
|
||||
jsFunc->SetProtoOrDynClass(thread, initialGeneratorFuncPrototype);
|
||||
jsFunc->SetCodeEntry(func->GetCodeEntry());
|
||||
|
||||
return jsFunc.GetTaggedValue();
|
||||
}
|
||||
|
||||
@ -1664,6 +1671,7 @@ JSTaggedValue RuntimeStubs::RuntimeDefineAsyncFunc(JSThread *thread, JSFunction
|
||||
JSHandle<JSHClass> dynclass = JSHandle<JSHClass>::Cast(env->GetAsyncFunctionClass());
|
||||
JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(method, dynclass, FunctionKind::ASYNC_FUNCTION);
|
||||
ASSERT_NO_ABRUPT_COMPLETION(thread);
|
||||
jsFunc->SetCodeEntry(func->GetCodeEntry());
|
||||
return jsFunc.GetTaggedValue();
|
||||
}
|
||||
|
||||
@ -1679,6 +1687,7 @@ JSTaggedValue RuntimeStubs::RuntimeDefineMethod(JSThread *thread, JSFunction *fu
|
||||
JSHandle<JSFunction> jsFunc = factory->NewJSFunctionByDynClass(method, dynclass, FunctionKind::NORMAL_FUNCTION);
|
||||
jsFunc->SetHomeObject(thread, homeObject);
|
||||
ASSERT_NO_ABRUPT_COMPLETION(thread);
|
||||
jsFunc->SetCodeEntry(func->GetCodeEntry());
|
||||
return jsFunc.GetTaggedValue();
|
||||
}
|
||||
|
||||
@ -1969,30 +1978,193 @@ JSTaggedValue RuntimeStubs::RuntimeOptSuspendGenerator(JSThread *thread, const J
|
||||
return generatorObjectHandle.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeOptNewObjDynRange(JSThread *thread, uintptr_t argv, uint32_t argc)
|
||||
JSTaggedValue RuntimeStubs::RuntimeOptConstruct(JSThread *thread, JSHandle<JSTaggedValue> ctor,
|
||||
JSHandle<JSTaggedValue> newTarget, JSHandle<JSTaggedValue> preArgs,
|
||||
JSHandle<TaggedArray> args)
|
||||
{
|
||||
JSTaggedType *args = reinterpret_cast<JSTaggedType *>(argv);
|
||||
JSHandle<JSTaggedValue> ctor = GetHArg<JSTaggedValue>(argv, argc, 0);
|
||||
JSHandle<JSTaggedValue> newTgt = GetHArg<JSTaggedValue>(argv, argc, 1);
|
||||
JSHandle<JSTaggedValue> thisObj = thread->GlobalConstants()->GetHandledUndefined();
|
||||
const size_t numCtorAndNewTgt = 2;
|
||||
STACK_ASSERT_SCOPE(thread);
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, ctor, thisObj, newTgt, argc - numCtorAndNewTgt);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
for (size_t i = 0; i < argc - numCtorAndNewTgt; ++i) {
|
||||
info->SetCallArg(i, JSTaggedValue(args[i + numCtorAndNewTgt]));
|
||||
if (newTarget->IsUndefined()) {
|
||||
newTarget = ctor;
|
||||
}
|
||||
|
||||
JSTaggedValue object = JSFunction::Construct(info);
|
||||
if (!(newTarget->IsConstructor() && ctor->IsConstructor())) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
if (ctor->IsJSFunction()) {
|
||||
return RuntimeOptConstructGeneric(thread, JSHandle<JSFunction>::Cast(ctor), newTarget, preArgs, args);
|
||||
}
|
||||
if (ctor->IsBoundFunction()) {
|
||||
return RuntimeOptConstructBoundFunction(
|
||||
thread, JSHandle<JSBoundFunction>::Cast(ctor), newTarget, preArgs, args);
|
||||
}
|
||||
if (ctor->IsJSProxy()) {
|
||||
return RuntimeOptConstructProxy(thread, JSHandle<JSProxy>::Cast(ctor), newTarget, preArgs, args);
|
||||
}
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor NonConstructor", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeOptConstructProxy(JSThread *thread, JSHandle<JSProxy> ctor,
|
||||
JSHandle<JSTaggedValue> newTgt, JSHandle<JSTaggedValue> preArgs,
|
||||
JSHandle<TaggedArray> args)
|
||||
{
|
||||
// step 1 ~ 4 get ProxyHandler and ProxyTarget
|
||||
JSHandle<JSTaggedValue> handler(thread, ctor->GetHandler());
|
||||
if (handler->IsNull()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor: handler is null", JSTaggedValue::Exception());
|
||||
}
|
||||
ASSERT(handler->IsJSObject());
|
||||
JSHandle<JSTaggedValue> target(thread, ctor->GetTarget());
|
||||
|
||||
// 5.Let trap be GetMethod(handler, "construct").
|
||||
JSHandle<JSTaggedValue> key(thread->GlobalConstants()->GetHandledProxyConstructString());
|
||||
JSHandle<JSTaggedValue> method = JSObject::GetMethod(thread, handler, key);
|
||||
|
||||
// 6.ReturnIfAbrupt(trap).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 7.If trap is undefined, then
|
||||
// a.Assert: target has a [[Construct]] internal method.
|
||||
// b.Return Construct(target, argumentsList, newTarget).
|
||||
if (method->IsUndefined()) {
|
||||
ASSERT(target->IsConstructor());
|
||||
return RuntimeOptConstruct(thread, target, newTgt, preArgs, args);
|
||||
}
|
||||
|
||||
// 8.Let argArray be CreateArrayFromList(argumentsList).
|
||||
uint32_t preArgsSize = preArgs->IsUndefined() ? 0 : JSHandle<TaggedArray>::Cast(preArgs)->GetLength();
|
||||
const uint32_t argsCount = args->GetLength();
|
||||
const uint32_t size = preArgsSize + argsCount;
|
||||
JSHandle<TaggedArray> arr = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(size);
|
||||
if (preArgsSize > 0) {
|
||||
JSHandle<TaggedArray> tgaPreArgs = JSHandle<TaggedArray>::Cast(preArgs);
|
||||
for (uint32_t i = 0; i < preArgsSize; ++i) {
|
||||
JSTaggedValue value = tgaPreArgs->Get(i);
|
||||
arr->Set(thread, i, value);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < argsCount; ++i) {
|
||||
JSTaggedValue value = args->Get(i);
|
||||
arr->Set(thread, i + preArgsSize, value);
|
||||
}
|
||||
|
||||
// step 8 ~ 9 Call(trap, handler, «target, argArray, newTarget »).
|
||||
const int32_t argsLength = 3; // 3: «target, argArray, newTarget »
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo *info = EcmaInterpreter::NewRuntimeCallInfo(thread, method, handler, undefined, argsLength);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(target.GetTaggedValue(), arr.GetTaggedValue(), newTgt.GetTaggedValue());
|
||||
JSTaggedValue newObjValue = JSFunction::Call(info);
|
||||
// 10.ReturnIfAbrupt(newObj).
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 11.If Type(newObj) is not Object, throw a TypeError exception.
|
||||
if (!newObjValue.IsECMAObject()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "new object is not object", JSTaggedValue::Exception());
|
||||
}
|
||||
// 12.Return newObj.
|
||||
return newObjValue;
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeOptConstructBoundFunction(JSThread *thread, JSHandle<JSBoundFunction> ctor,
|
||||
JSHandle<JSTaggedValue> newTgt,
|
||||
JSHandle<JSTaggedValue> preArgs,
|
||||
JSHandle<TaggedArray> args)
|
||||
{
|
||||
JSHandle<JSTaggedValue> target(thread, ctor->GetBoundTarget());
|
||||
ASSERT(target->IsConstructor());
|
||||
|
||||
JSHandle<TaggedArray> boundArgs(thread, ctor->GetBoundArguments());
|
||||
JSMutableHandle<JSTaggedValue> newPreArgs(thread, preArgs.GetTaggedValue());
|
||||
if (newPreArgs->IsUndefined()) {
|
||||
newPreArgs.Update(boundArgs.GetTaggedValue());
|
||||
} else {
|
||||
newPreArgs.Update(
|
||||
TaggedArray::Append(thread, boundArgs, JSHandle<TaggedArray>::Cast(preArgs)).GetTaggedValue());
|
||||
}
|
||||
JSMutableHandle<JSTaggedValue> newTargetMutable(thread, newTgt.GetTaggedValue());
|
||||
if (JSTaggedValue::SameValue(ctor.GetTaggedValue(), newTgt.GetTaggedValue())) {
|
||||
newTargetMutable.Update(target.GetTaggedValue());
|
||||
}
|
||||
return RuntimeOptConstruct(thread, target, newTargetMutable, newPreArgs, args);
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeOptConstructGeneric(JSThread *thread, JSHandle<JSFunction> ctor,
|
||||
JSHandle<JSTaggedValue> newTgt,
|
||||
JSHandle<JSTaggedValue> preArgs, JSHandle<TaggedArray> args)
|
||||
{
|
||||
if (!ctor->IsConstructor()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> obj(thread, JSTaggedValue::Undefined());
|
||||
if (ctor->IsBase()) {
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
obj = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(ctor, newTgt));
|
||||
}
|
||||
|
||||
uint32_t preArgsSize = preArgs->IsUndefined() ? 0 : JSHandle<TaggedArray>::Cast(preArgs)->GetLength();
|
||||
const uint32_t argsCount = args->GetLength();
|
||||
const uint32_t size = preArgsSize + argsCount;
|
||||
CVector<JSTaggedType> values;
|
||||
values.reserve(size);
|
||||
|
||||
JSMethod *method = ctor->GetCallTarget();
|
||||
if (method == nullptr) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Undefined target", JSTaggedValue::Exception());
|
||||
}
|
||||
|
||||
if (preArgsSize > 0) {
|
||||
JSHandle<TaggedArray> tgaPreArgs = JSHandle<TaggedArray>::Cast(preArgs);
|
||||
for (uint32_t i = 0; i < preArgsSize; ++i) {
|
||||
JSTaggedValue value = tgaPreArgs->Get(i);
|
||||
values.emplace_back(value.GetRawData());
|
||||
}
|
||||
for (uint32_t i = 0; i < argsCount; ++i) {
|
||||
values.emplace_back(args->Get(i).GetRawData());
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < argsCount; ++i) {
|
||||
values.emplace_back(args->Get(i).GetRawData());
|
||||
}
|
||||
}
|
||||
EcmaRuntimeCallInfo *info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread, JSHandle<JSTaggedValue>(ctor), obj, newTgt, size);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
info->SetCallArg(size, values.data());
|
||||
JSTaggedValue resultValue = EcmaInterpreter::Execute(info);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
// 9.3.2 [[Construct]] (argumentsList, newTarget)
|
||||
if (resultValue.IsECMAObject()) {
|
||||
return resultValue;
|
||||
}
|
||||
|
||||
if (ctor->IsBase()) {
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
if (!resultValue.IsUndefined()) {
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "function is non-constructor", JSTaggedValue::Exception());
|
||||
}
|
||||
return obj.GetTaggedValue();
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeOptNewObjDynRange(JSThread *thread, uintptr_t argv, uint32_t argc)
|
||||
{
|
||||
JSHandle<JSTaggedValue> ctor = GetHArg<JSTaggedValue>(argv, argc, 0);
|
||||
JSHandle<JSTaggedValue> newTgt = GetHArg<JSTaggedValue>(argv, argc, 1);
|
||||
JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
|
||||
const size_t numCtorAndNewTgt = 2;
|
||||
STACK_ASSERT_SCOPE(thread);
|
||||
size_t arrLength = argc - numCtorAndNewTgt;
|
||||
JSHandle<TaggedArray> args = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(arrLength);
|
||||
for (size_t i = 0; i < arrLength; ++i) {
|
||||
args->Set(thread, i, GetArg(argv, argc, i + numCtorAndNewTgt));
|
||||
}
|
||||
|
||||
JSTaggedValue object = RuntimeOptConstruct(thread, ctor, newTgt, undefined, args);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
if (!object.IsUndefined() && !object.IsECMAObject() && !JSHandle<JSFunction>(ctor)->IsBase()) {
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR,
|
||||
"Derived constructor must return object or undefined");
|
||||
thread->SetException(error.GetTaggedValue());
|
||||
THROW_TYPE_ERROR_AND_RETURN(thread, "Derived constructor must return object or undefined",
|
||||
JSTaggedValue::Exception());
|
||||
}
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,8 @@ class GlobalEnv;
|
||||
class JSThread;
|
||||
class JSFunction;
|
||||
class ObjectFactory;
|
||||
class JSBoundFunction;
|
||||
class JSProxy;
|
||||
|
||||
using JSFunctionEntryType = JSTaggedValue (*)(uintptr_t glue, uintptr_t prevFp, uint32_t expectedNumArgs,
|
||||
uint32_t actualNumArgs, const JSTaggedType argV[], uintptr_t codeAddr);
|
||||
@ -528,7 +530,19 @@ private:
|
||||
static inline JSTaggedValue RuntimeOptSuspendGenerator(JSThread *thread, const JSHandle<JSTaggedValue> &genObj,
|
||||
const JSHandle<JSTaggedValue> &value);
|
||||
static inline JSTaggedValue RuntimeOptNewObjDynRange(JSThread *thread, uintptr_t argv, uint32_t argc);
|
||||
|
||||
static inline JSTaggedValue RuntimeOptConstruct(JSThread *thread, JSHandle<JSTaggedValue> ctor,
|
||||
JSHandle<JSTaggedValue> newTarget, JSHandle<JSTaggedValue> preArgs,
|
||||
JSHandle<TaggedArray> args);
|
||||
static inline JSTaggedValue RuntimeOptConstructProxy(JSThread *thread, JSHandle<JSProxy> ctor,
|
||||
JSHandle<JSTaggedValue> newTgt,
|
||||
JSHandle<JSTaggedValue> preArgs, JSHandle<TaggedArray> args);
|
||||
static inline JSTaggedValue RuntimeOptConstructBoundFunction(JSThread *thread, JSHandle<JSBoundFunction> ctor,
|
||||
JSHandle<JSTaggedValue> newTgt,
|
||||
JSHandle<JSTaggedValue> preArgs,
|
||||
JSHandle<TaggedArray> args);
|
||||
static inline JSTaggedValue RuntimeOptConstructGeneric(JSThread *thread, JSHandle<JSFunction> ctor,
|
||||
JSHandle<JSTaggedValue> newTgt,
|
||||
JSHandle<JSTaggedValue> preArgs, JSHandle<TaggedArray> args);
|
||||
static inline JSTaggedValue RuntimeOptNewObjWithIHClass(JSThread *thread, uintptr_t argv, uint32_t argc);
|
||||
static inline JSTaggedValue RuntimeOptGetLexEnv(JSThread *thread);
|
||||
static inline void RuntimeOptSetLexEnv(JSThread *thread, JSTaggedValue lexEnv);
|
||||
|
Loading…
Reference in New Issue
Block a user