!2225 InstanceOf IR化

Merge pull request !2225 from lvfuqing/master
This commit is contained in:
openharmony_ci 2022-09-27 07:32:38 +00:00 committed by Gitee
commit 4dd4779b07
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 566 additions and 45 deletions

View File

@ -55,6 +55,9 @@ static constexpr uint64_t DOUBLE_SIGN_MASK = 0x8000000000000000ULL;
static constexpr uint64_t DOUBLE_EXPONENT_MASK = 0x7FFULL << DOUBLE_SIGNIFICAND_SIZE;
static constexpr uint64_t DOUBLE_SIGNIFICAND_MASK = 0x000FFFFFFFFFFFFFULL;
static constexpr uint64_t DOUBLE_HIDDEN_BIT = 1ULL << DOUBLE_SIGNIFICAND_SIZE;
static constexpr int32_t MINUS_ZERO_LOBITS = static_cast<int32_t>(0);
static constexpr int32_t MINUS_ZERO_HIBITS = static_cast<int32_t>(1) << 31;
static constexpr int64_t MINUS_ZERO_BITS = (static_cast<uint64_t>(MINUS_ZERO_HIBITS) << 32) | MINUS_ZERO_LOBITS;
static constexpr size_t INT64_BITS = 64;
static constexpr size_t INT32_BITS = 32;

View File

@ -1586,8 +1586,8 @@ DECLARE_ASM_HANDLER(HandleInstanceofImm8V8)
{
GateRef v0 = ReadInst8_1(pc);
GateRef obj = GetVregValue(sp, ZExtInt8ToPtr(v0));
GateRef result = CallRuntime(glue, RTSTUB_ID(InstanceOf), { obj, acc });
CHECK_EXCEPTION_WITH_ACC(result, INT_PTR(INSTANCEOF_IMM8_V8));
GateRef result = InstanceOf(glue, obj, acc);
CHECK_PENDING_EXCEPTION(result, INT_PTR(INSTANCEOF_IMM8_V8));
}
DECLARE_ASM_HANDLER(HandleStrictnoteqImm8V8)
@ -5362,7 +5362,7 @@ DECLARE_ASM_HANDLER(HandleCallarg0Imm8)
{
GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG0);
GateRef func = acc;
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8));
GateRef jumpSize = INT_PTR(CALLARG0_IMM8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_ARG0, {});
CHECK_PENDING_EXCEPTION(res, jumpSize);
}
@ -5372,7 +5372,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCallarg0PrefV8)
GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG0);
GateRef funcReg = ReadInst8_1(pc);
GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8));
GateRef jumpSize = INT_PTR(DEPRECATED_CALLARG0_PREF_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::DEPRECATED_CALL_ARG0, {});
CHECK_PENDING_EXCEPTION(res, jumpSize);
}
@ -5383,7 +5383,7 @@ DECLARE_ASM_HANDLER(HandleCallarg1Imm8V8)
GateRef a0 = ReadInst8_1(pc);
GateRef func = acc;
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8));
GateRef jumpSize = INT_PTR(CALLARG1_IMM8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_ARG1, { a0Value });
CHECK_PENDING_EXCEPTION(res, jumpSize);
}
@ -5395,7 +5395,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCallarg1PrefV8V8)
GateRef a0 = ReadInst8_2(pc);
GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg));
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8_V8));
GateRef jumpSize = INT_PTR(DEPRECATED_CALLARG1_PREF_V8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::DEPRECATED_CALL_ARG1, { a0Value });
CHECK_PENDING_EXCEPTION(res, jumpSize);
}
@ -5408,7 +5408,7 @@ DECLARE_ASM_HANDLER(HandleCallargs2Imm8V8V8)
GateRef func = acc;
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8_V8));
GateRef jumpSize = INT_PTR(CALLARGS2_IMM8_V8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::CALL_ARG2, { a0Value, a1Value });
CHECK_PENDING_EXCEPTION(res, jumpSize);
@ -5423,7 +5423,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCallargs2PrefV8V8V8)
GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg));
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8_V8_V8));
GateRef jumpSize = INT_PTR(DEPRECATED_CALLARGS2_PREF_V8_V8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::DEPRECATED_CALL_ARG2, { a0Value, a1Value });
CHECK_PENDING_EXCEPTION(res, jumpSize);
@ -5439,7 +5439,7 @@ DECLARE_ASM_HANDLER(HandleCallargs3Imm8V8V8V8)
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1));
GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8_V8_V8));
GateRef jumpSize = INT_PTR(CALLARGS3_IMM8_V8_V8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::CALL_ARG3, { a0Value, a1Value, a2Value });
CHECK_PENDING_EXCEPTION(res, jumpSize);
@ -5456,7 +5456,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCallargs3PrefV8V8V8V8)
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1));
GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8_V8_V8_V8));
GateRef jumpSize = INT_PTR(DEPRECATED_CALLARGS3_PREF_V8_V8_V8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::DEPRECATED_CALL_ARG3, { a0Value, a1Value, a2Value });
CHECK_PENDING_EXCEPTION(res, jumpSize);
@ -5467,7 +5467,7 @@ DECLARE_ASM_HANDLER(HandleCallrangeImm8Imm8V8)
GateRef actualNumArgs = ZExtInt8ToInt32(ReadInst8_1(pc));
GateRef func = acc;
GateRef argv = PtrAdd(sp, PtrMul(ZExtInt8ToPtr(ReadInst8_2(pc)), IntPtr(8))); // 8: byteSize
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_IMM8_V8));
GateRef jumpSize = INT_PTR(CALLRANGE_IMM8_IMM8_V8);
GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::CALL_WITH_ARGV, { numArgs, argv });
@ -5479,7 +5479,7 @@ DECLARE_ASM_HANDLER(HandleWideCallrangePrefImm16V8)
GateRef actualNumArgs = ZExtInt16ToInt32(ReadInst16_1(pc));
GateRef func = acc;
GateRef argv = PtrAdd(sp, PtrMul(ZExtInt8ToPtr(ReadInst8_2(pc)), IntPtr(8))); // 8: byteSize
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8));
GateRef jumpSize = INT_PTR(WIDE_CALLRANGE_PREF_IMM16_V8);
GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::CALL_WITH_ARGV, { numArgs, argv });
@ -5493,7 +5493,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCallrangePrefImm16V8)
GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg));
GateRef argv = PtrAdd(sp, PtrMul(
PtrAdd(ZExtInt8ToPtr(funcReg), IntPtr(1)), IntPtr(8))); // 1: skip function
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8));
GateRef jumpSize = INT_PTR(DEPRECATED_CALLRANGE_PREF_IMM16_V8);
GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::DEPRECATED_CALL_WITH_ARGV, { numArgs, argv });
@ -5508,7 +5508,7 @@ DECLARE_ASM_HANDLER(HandleCallthisrangeImm8Imm8V8)
GateRef thisValue = GetVregValue(sp, thisReg);
GateRef argv = PtrAdd(sp, PtrMul(
PtrAdd(thisReg, IntPtr(1)), IntPtr(8))); // 1: skip this
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_IMM8_V8));
GateRef jumpSize = INT_PTR(CALLTHISRANGE_IMM8_IMM8_V8);
GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::CALL_THIS_WITH_ARGV, { numArgs, argv, thisValue });
@ -5523,7 +5523,7 @@ DECLARE_ASM_HANDLER(HandleWideCallthisrangePrefImm16V8)
GateRef thisValue = GetVregValue(sp, thisReg);
GateRef argv = PtrAdd(sp, PtrMul(
PtrAdd(thisReg, IntPtr(1)), IntPtr(8))); // 1: skip this
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8));
GateRef jumpSize = INT_PTR(WIDE_CALLTHISRANGE_PREF_IMM16_V8);
GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::CALL_THIS_WITH_ARGV, { numArgs, argv, thisValue });
@ -5539,7 +5539,7 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCallthisrangePrefImm16V8)
GateRef thisValue = GetVregValue(sp, PtrAdd(funcReg, IntPtr(1)));
GateRef argv = PtrAdd(sp, PtrMul(
PtrAdd(funcReg, IntPtr(2)), IntPtr(8))); // 2: skip function&this
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::PREF_IMM16_V8));
GateRef jumpSize = INT_PTR(DEPRECATED_CALLTHISRANGE_PREF_IMM16_V8);
GateRef numArgs = ChangeInt32ToIntPtr(actualNumArgs);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::DEPRECATED_CALL_THIS_WITH_ARGV, { numArgs, argv, thisValue });
@ -5551,7 +5551,7 @@ DECLARE_ASM_HANDLER(HandleCallthis0Imm8V8)
GateRef actualNumArgs = Int32(InterpreterAssembly::ActualNumArgsOfCall::CALLARG0);
GateRef thisValue = GetVregValue(sp, ZExtInt8ToPtr(ReadInst8_1(pc)));
GateRef func = acc;
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8));
GateRef jumpSize = INT_PTR(CALLTHIS0_IMM8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_THIS_ARG0, { thisValue });
CHECK_PENDING_EXCEPTION(res, jumpSize);
}
@ -5563,7 +5563,7 @@ DECLARE_ASM_HANDLER(HandleCallthis1Imm8V8V8)
GateRef a0 = ReadInst8_2(pc);
GateRef func = acc;
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8_V8));
GateRef jumpSize = INT_PTR(CALLTHIS1_IMM8_V8_V8);
GateRef res =
JSCallDispatch(glue, func, actualNumArgs, jumpSize, JSCallMode::CALL_THIS_ARG1, { a0Value, thisValue });
CHECK_PENDING_EXCEPTION(res, jumpSize);
@ -5578,7 +5578,7 @@ DECLARE_ASM_HANDLER(HandleCallthis2Imm8V8V8V8)
GateRef func = acc;
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8_V8_V8));
GateRef jumpSize = INT_PTR(CALLTHIS2_IMM8_V8_V8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::CALL_THIS_ARG2, { a0Value, a1Value, thisValue });
CHECK_PENDING_EXCEPTION(res, jumpSize);
@ -5595,7 +5595,7 @@ DECLARE_ASM_HANDLER(HandleCallthis3Imm8V8V8V8V8)
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0));
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1));
GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2));
GateRef jumpSize = IntPtr(BytecodeInstruction::Size(BytecodeInstruction::Format::IMM8_V8_V8_V8_V8));
GateRef jumpSize = INT_PTR(CALLTHIS3_IMM8_V8_V8_V8_V8);
GateRef res = JSCallDispatch(glue, func, actualNumArgs, jumpSize,
JSCallMode::CALL_THIS_ARG3, { a0Value, a1Value, a2Value, thisValue });
CHECK_PENDING_EXCEPTION(res, jumpSize);

View File

@ -1002,8 +1002,8 @@ GateRef StubBuilder::TaggedIsBigInt(GateRef obj)
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
DEFVARIABLE(result, VariableType::BOOL(), False());
Label isHeapObject(env);
DEFVARIABLE(result, VariableType::BOOL(), False());
Branch(TaggedIsHeapObject(obj), &isHeapObject, &exit);
Bind(&isHeapObject);
{
@ -2884,6 +2884,516 @@ GateRef StubBuilder::FastTypeOf(GateRef glue, GateRef obj)
return ret;
}
GateRef StubBuilder::InstanceOf(GateRef glue, GateRef object, GateRef target)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
Label exit(env);
// 1.If Type(target) is not Object, throw a TypeError exception.
Label targetIsHeapObject(env);
Label targetIsEcmaObject(env);
Label targetNotEcmaObject(env);
Branch(TaggedIsHeapObject(target), &targetIsHeapObject, &targetNotEcmaObject);
Bind(&targetIsHeapObject);
Branch(TaggedObjectIsEcmaObject(target), &targetIsEcmaObject, &targetNotEcmaObject);
Bind(&targetNotEcmaObject);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(TargetTypeNotObject));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
result = Exception();
Jump(&exit);
}
Bind(&targetIsEcmaObject);
{
// 2.Let instOfHandler be GetMethod(target, @@hasInstance).
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
GateRef hasInstanceSymbol = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv,
GlobalEnv::HASINSTANCE_SYMBOL_INDEX);
GateRef instof = GetMethod(glue, target, hasInstanceSymbol);
// 3.ReturnIfAbrupt(instOfHandler).
Label isPendingException1(env);
Label noPendingException1(env);
Branch(HasPendingException(glue), &isPendingException1, &noPendingException1);
Bind(&isPendingException1);
{
result = Exception();
Jump(&exit);
}
Bind(&noPendingException1);
// 4.If instOfHandler is not undefined, then
Label instOfNotUndefined(env);
Label instOfIsUndefined(env);
Branch(TaggedIsUndefined(instof), &instOfIsUndefined, &instOfNotUndefined);
Bind(&instOfNotUndefined);
{
GateRef retValue = JSCallDispatch(glue, instof, Int32(1), 0, JSCallMode::CALL_SETTER, { target, object });
result = FastToBoolean(retValue);
Jump(&exit);
}
Bind(&instOfIsUndefined);
{
// 5.If IsCallable(target) is false, throw a TypeError exception.
Label targetIsCallable1(env);
Label targetNotCallable1(env);
Branch(IsCallable(target), &targetIsCallable1, &targetNotCallable1);
Bind(&targetNotCallable1);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
result = Exception();
Jump(&exit);
}
Bind(&targetIsCallable1);
{
// 6.Return ? OrdinaryHasInstance(target, object).
result = OrdinaryHasInstance(glue, target, object);
Jump(&exit);
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::GetMethod(GateRef glue, GateRef obj, GateRef key)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
Label exit(env);
GateRef value = FastGetPropertyByName(glue, obj, key);
Label isPendingException2(env);
Label noPendingException2(env);
Branch(HasPendingException(glue), &isPendingException2, &noPendingException2);
Bind(&isPendingException2);
{
result = Exception();
Jump(&exit);
}
Bind(&noPendingException2);
Label valueIsUndefinedOrNull(env);
Label valueNotUndefinedOrNull(env);
Branch(TaggedIsUndefinedOrNull(value), &valueIsUndefinedOrNull, &valueNotUndefinedOrNull);
Bind(&valueIsUndefinedOrNull);
{
result = Undefined();
Jump(&exit);
}
Bind(&valueNotUndefinedOrNull);
{
Label valueIsCallable(env);
Label valueNotCallable(env);
Branch(IsCallable(value), &valueIsCallable, &valueNotCallable);
Bind(&valueNotCallable);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(NonCallable));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
result = Exception();
Jump(&exit);
}
Bind(&valueIsCallable);
{
result = value;
Jump(&exit);
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
Label exit(env);
Label checkResult(env);
Label fastpath(env);
Label slowpath(env);
Branch(TaggedIsHeapObject(obj), &fastpath, &slowpath);
Bind(&fastpath);
{
result = GetPropertyByName(glue, obj, key);
Branch(TaggedIsHole(*result), &slowpath, &exit);
}
Bind(&slowpath);
{
result = CallRuntime(glue, RTSTUB_ID(LoadICByName),
{ Undefined(), obj, key, Int64ToTaggedPtr(Int32(0)) });
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
Label exit(env);
DEFVARIABLE(object, VariableType::JS_ANY(), obj);
// 1. If IsCallable(C) is false, return false.
Label targetIsCallable2(env);
Label targetNotCallable2(env);
Branch(IsCallable(target), &targetIsCallable2, &targetNotCallable2);
Bind(&targetNotCallable2);
{
result = TaggedFalse();
Jump(&exit);
}
Bind(&targetIsCallable2);
{
// 2. If C has a [[BoundTargetFunction]] internal slot, then
// a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
// b. Return InstanceofOperator(O,BC) (see 12.9.4).
Label targetIsBoundFunction(env);
Label targetNotBoundFunction(env);
Branch(IsBoundFunction(target), &targetIsBoundFunction, &targetNotBoundFunction);
Bind(&targetIsBoundFunction);
{
GateRef boundTarget = Load(VariableType::JS_ANY(), target, IntPtr(JSBoundFunction::BOUND_TARGET_OFFSET));
result = CallRuntime(glue, RTSTUB_ID(InstanceOf), { obj, boundTarget });
Jump(&exit);
}
Bind(&targetNotBoundFunction);
{
// 3. If Type(O) is not Object, return false
Label objIsHeapObject(env);
Label objIsEcmaObject(env);
Label objNotEcmaObject(env);
Branch(TaggedIsHeapObject(obj), &objIsHeapObject, &objNotEcmaObject);
Bind(&objIsHeapObject);
Branch(TaggedObjectIsEcmaObject(obj), &objIsEcmaObject, &objNotEcmaObject);
Bind(&objNotEcmaObject);
{
result = TaggedFalse();
Jump(&exit);
}
Bind(&objIsEcmaObject);
{
// 4. Let P be Get(C, "prototype").
auto prototypeString = GetGlobalConstantValue(
VariableType::JS_POINTER(), glue, ConstantIndex::PROTOTYPE_STRING_INDEX);
GateRef constructorPrototype = FastGetPropertyByName(glue, target, prototypeString);
// 5. ReturnIfAbrupt(P).
// no throw exception, so needn't return
Label isPendingException3(env);
Label noPendingException3(env);
Branch(HasPendingException(glue), &isPendingException3, &noPendingException3);
Bind(&isPendingException3);
{
result = Exception();
Jump(&exit);
}
Bind(&noPendingException3);
// 6. If Type(P) is not Object, throw a TypeError exception.
Label constructorPrototypeIsHeapObject(env);
Label constructorPrototypeIsEcmaObject(env);
Label constructorPrototypeNotEcmaObject(env);
Branch(TaggedIsHeapObject(constructorPrototype), &constructorPrototypeIsHeapObject,
&constructorPrototypeNotEcmaObject);
Bind(&constructorPrototypeIsHeapObject);
Branch(TaggedObjectIsEcmaObject(constructorPrototype), &constructorPrototypeIsEcmaObject,
&constructorPrototypeNotEcmaObject);
Bind(&constructorPrototypeNotEcmaObject);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(InstanceOfErrorTargetNotCallable));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
result = Exception();
Jump(&exit);
}
Bind(&constructorPrototypeIsEcmaObject);
{
// 7. Repeat
// a.Let O be O.[[GetPrototypeOf]]().
// b.ReturnIfAbrupt(O).
// c.If O is null, return false.
// d.If SameValue(P, O) is true, return true.
Label loopHead(env);
Label loopEnd(env);
Label afterLoop(env);
Label strictEqual1(env);
Label notStrictEqual1(env);
Label shouldReturn(env);
Label shouldContinue(env);
Branch(TaggedIsNull(*object), &afterLoop, &loopHead);
LoopBegin(&loopHead);
{
GateRef isEqual = SameValue(glue, *object, constructorPrototype);
Branch(isEqual, &strictEqual1, &notStrictEqual1);
Bind(&strictEqual1);
{
result = TaggedTrue();
Jump(&exit);
}
Bind(&notStrictEqual1);
{
object = GetPrototype(glue, *object);
Branch(HasPendingException(glue), &shouldReturn, &shouldContinue);
Bind(&shouldReturn);
{
result = Exception();
Jump(&exit);
}
}
Bind(&shouldContinue);
Branch(TaggedIsNull(*object), &afterLoop, &loopEnd);
}
Bind(&loopEnd);
LoopEnd(&loopHead);
Bind(&afterLoop);
{
result = TaggedFalse();
Jump(&exit);
}
}
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::GetPrototype(GateRef glue, GateRef object)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::JS_ANY(), Hole());
Label exit(env);
Label objectIsHeapObject(env);
Label objectIsEcmaObject(env);
Label objectNotEcmaObject(env);
Branch(TaggedIsHeapObject(object), &objectIsHeapObject, &objectNotEcmaObject);
Bind(&objectIsHeapObject);
Branch(TaggedObjectIsEcmaObject(object), &objectIsEcmaObject, &objectNotEcmaObject);
Bind(&objectNotEcmaObject);
{
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(CanNotGetNotEcmaObject));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
result = Exception();
Jump(&exit);
}
Bind(&objectIsEcmaObject);
{
Label objectIsJsProxy(env);
Label objectNotIsJsProxy(env);
Branch(IsJsProxy(object), &objectIsJsProxy, &objectNotIsJsProxy);
Bind(&objectIsJsProxy);
{
result = CallRuntime(glue, RTSTUB_ID(CallGetPrototype), { object });
Jump(&exit);
}
Bind(&objectNotIsJsProxy);
{
result = GetPrototypeFromHClass(LoadHClass(object));
Jump(&exit);
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::SameValue(GateRef glue, GateRef left, GateRef right)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::BOOL(), False());
Label exit(env);
DEFVARIABLE(doubleLeft, VariableType::FLOAT64(), Double(0.0));
DEFVARIABLE(doubleRight, VariableType::FLOAT64(), Double(0.0));
Label strictEqual2(env);
Label stringEqualCheck(env);
Label stringCompare(env);
Label bigIntEqualCheck(env);
Label numberEqualCheck1(env);
Branch(Equal(left, right), &strictEqual2, &numberEqualCheck1);
Bind(&strictEqual2);
{
result = True();
Jump(&exit);
}
Bind(&numberEqualCheck1);
{
Label leftIsNumber(env);
Label leftIsNotNumber(env);
Branch(TaggedIsNumber(left), &leftIsNumber, &leftIsNotNumber);
Bind(&leftIsNumber);
{
Label rightIsNumber(env);
Branch(TaggedIsNumber(right), &rightIsNumber, &exit);
Bind(&rightIsNumber);
{
Label numberEqualCheck2(env);
Label leftIsInt(env);
Label leftNotInt(env);
Label getRight(env);
Branch(TaggedIsInt(left), &leftIsInt, &leftNotInt);
Bind(&leftIsInt);
{
doubleLeft = ChangeInt32ToFloat64(TaggedCastToInt32(left));
Jump(&getRight);
}
Bind(&leftNotInt);
{
doubleLeft = TaggedCastToDouble(left);
Jump(&getRight);
}
Bind(&getRight);
{
Label rightIsInt(env);
Label rightNotInt(env);
Branch(TaggedIsInt(right), &rightIsInt, &rightNotInt);
Bind(&rightIsInt);
{
doubleRight = ChangeInt32ToFloat64(TaggedCastToInt32(right));
Jump(&numberEqualCheck2);
}
Bind(&rightNotInt);
{
doubleRight = TaggedCastToDouble(right);
Jump(&numberEqualCheck2);
}
}
Bind(&numberEqualCheck2);
{
Label boolAndCheck(env);
Label signbitCheck(env);
Branch(DoubleEqual(*doubleLeft, *doubleRight), &signbitCheck, &boolAndCheck);
Bind(&signbitCheck);
{
GateRef leftEncoding = CastDoubleToInt64(*doubleLeft);
GateRef RightEncoding = CastDoubleToInt64(*doubleRight);
Label leftIsMinusZero(env);
Label leftNotMinusZero(env);
Branch(Int64Equal(leftEncoding, Int64(base::MINUS_ZERO_BITS)),
&leftIsMinusZero, &leftNotMinusZero);
Bind(&leftIsMinusZero);
{
Label rightIsMinusZero(env);
Branch(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &rightIsMinusZero, &exit);
Bind(&rightIsMinusZero);
{
result = True();
Jump(&exit);
}
}
Bind(&leftNotMinusZero);
{
Label rightNotMinusZero(env);
Branch(Int64Equal(RightEncoding, Int64(base::MINUS_ZERO_BITS)), &exit, &rightNotMinusZero);
Bind(&rightNotMinusZero);
{
result = True();
Jump(&exit);
}
}
}
Bind(&boolAndCheck);
{
result = BoolAnd(DoubleIsNAN(*doubleLeft), DoubleIsNAN(*doubleRight));
Jump(&exit);
}
}
}
}
Bind(&leftIsNotNumber);
Branch(TaggedIsNumber(right), &exit, &stringEqualCheck);
Bind(&stringEqualCheck);
Branch(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
Bind(&stringCompare);
{
result = FastStringEqual(glue, left, right);
Jump(&exit);
}
Bind(&bigIntEqualCheck);
{
Label leftIsBigInt(env);
Label leftIsNotBigInt(env);
Branch(TaggedIsBigInt(left), &leftIsBigInt, &exit);
Bind(&leftIsBigInt);
{
Label rightIsBigInt(env);
Branch(TaggedIsBigInt(right), &rightIsBigInt, &exit);
Bind(&rightIsBigInt);
result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(BigIntEquals), { left, right });
Jump(&exit);
}
}
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::FastStringEqual(GateRef glue, GateRef left, GateRef right)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
DEFVARIABLE(result, VariableType::BOOL(), False());
Label exit(env);
Label lengthCompare(env);
Label hashcodeCompare(env);
Label contentsCompare(env);
Branch(Int32Equal(ZExtInt1ToInt32(IsUtf16String(left)), ZExtInt1ToInt32(IsUtf16String(right))),
&lengthCompare, &exit);
Bind(&lengthCompare);
Branch(Int32Equal(GetLengthFromString(left), GetLengthFromString(right)), &hashcodeCompare,
&exit);
Bind(&hashcodeCompare);
Branch(Int32Equal(GetHashcodeFromString(glue, left), GetHashcodeFromString(glue, right)), &contentsCompare,
&exit);
Bind(&contentsCompare);
{
result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(StringsAreEquals), { left, right });
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef StubBuilder::FastStrictEqual(GateRef glue, GateRef left, GateRef right)
{
auto env = GetEnvironment();
@ -2958,22 +3468,8 @@ GateRef StubBuilder::FastStrictEqual(GateRef glue, GateRef left, GateRef right)
Branch(BothAreString(left, right), &stringCompare, &bigIntEqualCheck);
Bind(&stringCompare);
{
Label lengthCompare(env);
Label hashcodeCompare(env);
Label contentsCompare(env);
Branch(Int32Equal(ZExtInt1ToInt32(IsUtf16String(left)), ZExtInt1ToInt32(IsUtf16String(right))),
&lengthCompare, &exit);
Bind(&lengthCompare);
Branch(Int32Equal(GetLengthFromString(left), GetLengthFromString(right)), &hashcodeCompare,
&exit);
Bind(&hashcodeCompare);
Branch(Int32Equal(GetHashcodeFromString(glue, left), GetHashcodeFromString(glue, right)), &contentsCompare,
&exit);
Bind(&contentsCompare);
{
result = UpdateLeaveFrameAndCallNGCRuntime(glue, RTSTUB_ID(StringsAreEquals), { left, right });
Jump(&exit);
}
result = FastStringEqual(glue, left, right);
Jump(&exit);
}
Bind(&bigIntEqualCheck);
{

View File

@ -267,11 +267,16 @@ public:
GateRef GetProtoCell(GateRef object);
GateRef GetPrototypeHandlerHolder(GateRef object);
GateRef GetPrototypeHandlerHandlerInfo(GateRef object);
GateRef GetPrototype(GateRef glue, GateRef object);
GateRef GetHasChanged(GateRef object);
GateRef HclassIsPrototypeHandler(GateRef hClass);
GateRef HclassIsTransitionHandler(GateRef hClass);
GateRef HclassIsPropertyBox(GateRef hClass);
GateRef PropAttrGetOffset(GateRef attr);
GateRef InstanceOf(GateRef glue, GateRef object, GateRef target);
GateRef OrdinaryHasInstance(GateRef glue, GateRef target, GateRef obj);
GateRef SameValue(GateRef glue, GateRef left, GateRef right);
// SetDictionaryOrder func in property_attribute.h
GateRef SetDictionaryOrderFieldInPropAttr(GateRef attr, GateRef value);
GateRef GetPrototypeFromHClass(GateRef hClass);
@ -399,6 +404,7 @@ public:
void SetValueWithBarrier(GateRef glue, GateRef obj, GateRef offset, GateRef value);
GateRef GetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index);
GateRef GetPropertyByName(GateRef glue, GateRef receiver, GateRef key);
GateRef FastGetPropertyByName(GateRef glue, GateRef obj, GateRef key);
GateRef GetPropertyByValue(GateRef glue, GateRef receiver, GateRef keyValue);
GateRef SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn);
GateRef SetPropertyByName(GateRef glue, GateRef receiver, GateRef key,
@ -422,6 +428,7 @@ public:
// fast path
GateRef FastEqual(GateRef left, GateRef right);
GateRef FastStrictEqual(GateRef glue, GateRef left, GateRef right);
GateRef FastStringEqual(GateRef glue, GateRef left, GateRef right);
GateRef FastMod(GateRef gule, GateRef left, GateRef right);
GateRef FastTypeOf(GateRef left, GateRef right);
GateRef FastMul(GateRef left, GateRef right);
@ -445,6 +452,7 @@ public:
GateRef IsNativeMethod(GateRef method);
GateRef HasAotCode(GateRef method);
GateRef GetExpectedNumOfArgs(GateRef method);
GateRef GetMethod(GateRef glue, GateRef obj, GateRef key);
// proxy operator
GateRef GetMethodFromJSProxy(GateRef proxy);
GateRef GetHandlerFromJSProxy(GateRef proxy);

View File

@ -24,14 +24,19 @@
namespace panda::ecmascript {
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define COMMON_MESSAGE_STRING_LIST(V) \
V(SetReadOnlyProperty, "Cannot set readonly property") \
V(FunctionCallNotConstructor, "class constructor cannot call") \
V(SetPropertyWhenNotExtensible, "Cannot add property in prevent extensions ") \
V(GetPropertyOutOfBounds, "Get Property index out-of-bounds") \
V(CanNotSetPropertyOnContainer, "Cannot set property on Container") \
V(NonCallable, "CallObj is NonCallable") \
V(INT32_VALUE, "value: %ld")
#define COMMON_MESSAGE_STRING_LIST(V) \
V(SetReadOnlyProperty, "Cannot set readonly property") \
V(FunctionCallNotConstructor, "class constructor cannot call") \
V(SetPropertyWhenNotExtensible, "Cannot add property in prevent extensions ") \
V(GetPropertyOutOfBounds, "Get Property index out-of-bounds") \
V(CanNotSetPropertyOnContainer, "Cannot set property on Container") \
V(NonCallable, "CallObj is NonCallable") \
V(ASM_INTERPRETER_STUB_NAME, "ASM_INTERPRETER stub name: ") \
V(OPCODE_OVERFLOW, "opcode overflow!") \
V(INT32_VALUE, "value: %ld") \
V(TargetTypeNotObject, "Type of target is not Object") \
V(CanNotGetNotEcmaObject, "Can not get Prototype on non ECMA Object") \
V(InstanceOfErrorTargetNotCallable, "InstanceOf error when target is not Callable")
class MessageString {
public:

View File

@ -385,6 +385,14 @@ DEF_RUNTIME_STUBS(Dec)
return RuntimeDec(thread, value).GetRawData();
}
DEF_RUNTIME_STUBS(CallGetPrototype)
{
RUNTIME_STUBS_HEADER(CallGetPrototype);
JSHandle<JSProxy> proxy = GetHArg<JSProxy>(argv, argc, 0); // 0: means the zeroth parameter
return JSProxy::GetPrototype(thread, proxy).GetRawData();
}
DEF_RUNTIME_STUBS(Exp)
{
RUNTIME_STUBS_HEADER(Exp);

View File

@ -99,6 +99,7 @@ using JSFunctionEntryType = JSTaggedValue (*)(uintptr_t glue, uintptr_t prevFp,
V(AllocateInYoung) \
V(CallInternalGetter) \
V(CallInternalSetter) \
V(CallGetPrototype) \
V(ThrowTypeError) \
V(DebugBreak) \
V(GetHash32) \