|
|
@@ -6468,6 +6468,12 @@ GlobOpt::GetConstantVar(IR::Opnd *opnd, Value *val)
|
|
|
return Js::TaggedInt::ToVarUnchecked(opnd->AsIntConstOpnd()->AsInt32());
|
|
|
}
|
|
|
}
|
|
|
+#if FLOATVAR
|
|
|
+ else if (opnd->IsFloatConstOpnd())
|
|
|
+ {
|
|
|
+ return Js::JavascriptNumber::ToVar(opnd->AsFloatConstOpnd()->m_value);
|
|
|
+ }
|
|
|
+#endif
|
|
|
else if (opnd->IsRegOpnd() && opnd->AsRegOpnd()->m_sym->IsSingleDef())
|
|
|
{
|
|
|
if (valueInfo->IsBoolean())
|
|
|
@@ -6489,19 +6495,110 @@ GlobOpt::GetConstantVar(IR::Opnd *opnd, Value *val)
|
|
|
{
|
|
|
return (Js::Var)this->func->GetScriptContextInfo()->GetNullAddr();
|
|
|
}
|
|
|
+#if FLOATVAR
|
|
|
+ else if (valueInfo->IsFloat())
|
|
|
+ {
|
|
|
+ IR::Instr * defInstr = opnd->AsRegOpnd()->m_sym->GetInstrDef();
|
|
|
+ if (defInstr->m_opcode == Js::OpCode::LdC_F8_R8 && defInstr->GetSrc1()->IsFloatConstOpnd())
|
|
|
+ {
|
|
|
+ return Js::JavascriptNumber::ToVar(defInstr->GetSrc1()->AsFloatConstOpnd()->m_value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
-bool BoolAndIntStaticAndTypeMismatch(Value* src1Val, Value* src2Val, Js::Var src1Var, Js::Var src2Var)
|
|
|
+namespace
|
|
|
{
|
|
|
- ValueInfo *src1ValInfo = src1Val->GetValueInfo();
|
|
|
- ValueInfo *src2ValInfo = src2Val->GetValueInfo();
|
|
|
- return (src1ValInfo->IsNumber() && src1Var && src2ValInfo->IsBoolean() && src1Var != Js::TaggedInt::ToVarUnchecked(0) && src1Var != Js::TaggedInt::ToVarUnchecked(1)) ||
|
|
|
- (src2ValInfo->IsNumber() && src2Var && src1ValInfo->IsBoolean() && src2Var != Js::TaggedInt::ToVarUnchecked(0) && src2Var != Js::TaggedInt::ToVarUnchecked(1));
|
|
|
-}
|
|
|
+ bool TryCompIntAndFloat(bool * result, Js::Var left, Js::Var right)
|
|
|
+ {
|
|
|
+ if (Js::TaggedInt::Is(left))
|
|
|
+ {
|
|
|
+ // If both are tagged ints we should not get here.
|
|
|
+ Assert(!Js::TaggedInt::Is(right));
|
|
|
+ if (Js::JavascriptNumber::Is_NoTaggedIntCheck(right))
|
|
|
+ {
|
|
|
+ double value = Js::JavascriptNumber::GetValue(right);
|
|
|
+ *result = (Js::TaggedInt::ToInt32(left) == value);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool Op_JitEq(bool * result, Value * src1Val, Value * src2Val, Js::Var src1Var, Js::Var src2Var, Func * func, bool isStrict)
|
|
|
+ {
|
|
|
+ Assert(src1Val != nullptr && src2Val != nullptr);
|
|
|
+ Assert(src1Var != nullptr && src2Var != nullptr);
|
|
|
+
|
|
|
+ if (src1Var == src2Var)
|
|
|
+ {
|
|
|
+ if (Js::TaggedInt::Is(src1Var))
|
|
|
+ {
|
|
|
+ *result = true;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!isStrict && src1Val->GetValueInfo()->IsNotFloat())
|
|
|
+ {
|
|
|
+ // If the vars are equal and they are not NaN, non-strict equal returns true. Not float guarantees not NaN.
|
|
|
+ *result = true;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+#if FLOATVAR
|
|
|
+ if (Js::JavascriptNumber::Is_NoTaggedIntCheck(src1Var))
|
|
|
+ {
|
|
|
+ *result = !Js::JavascriptNumber::IsNan(Js::JavascriptNumber::GetValue(src1Var));
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetTrueAddr()) ||
|
|
|
+ src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetFalseAddr()) ||
|
|
|
+ src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetNullAddr()) ||
|
|
|
+ src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetUndefinedAddr()))
|
|
|
+ {
|
|
|
+ *result = true;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Other var comparisons require the runtime to prove.
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+#if FLOATVAR
|
|
|
+ if (TryCompIntAndFloat(result, src1Var, src2Var) || TryCompIntAndFloat(result, src2Var, src1Var))
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+#endif
|
|
|
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool Op_JitNeq(bool * result, Value * src1Val, Value * src2Val, Js::Var src1Var, Js::Var src2Var, Func * func, bool isStrict)
|
|
|
+ {
|
|
|
+ if (Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, func, isStrict))
|
|
|
+ {
|
|
|
+ *result = !*result;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool BoolAndIntStaticAndTypeMismatch(Value* src1Val, Value* src2Val, Js::Var src1Var, Js::Var src2Var)
|
|
|
+ {
|
|
|
+ ValueInfo *src1ValInfo = src1Val->GetValueInfo();
|
|
|
+ ValueInfo *src2ValInfo = src2Val->GetValueInfo();
|
|
|
+ return (src1ValInfo->IsNumber() && src1Var && src2ValInfo->IsBoolean() && src1Var != Js::TaggedInt::ToVarUnchecked(0) && src1Var != Js::TaggedInt::ToVarUnchecked(1)) ||
|
|
|
+ (src2ValInfo->IsNumber() && src2Var && src1ValInfo->IsBoolean() && src2Var != Js::TaggedInt::ToVarUnchecked(0) && src2Var != Js::TaggedInt::ToVarUnchecked(1));
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
bool
|
|
|
GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2Val, Js::Var src1Var, Js::Var src2Var, bool *result)
|
|
|
@@ -6629,12 +6726,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
|
|
|
+ if (!Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, this->func, false /* isStrict */))
|
|
|
{
|
|
|
- // TODO: OOP JIT, const folding
|
|
|
return false;
|
|
|
}
|
|
|
- *result = Js::JavascriptOperators::Equal(src1Var, src2Var, this->func->GetScriptContext());
|
|
|
}
|
|
|
break;
|
|
|
case Js::OpCode::BrNeq_A:
|
|
|
@@ -6661,12 +6756,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
|
|
|
+ if (!Op_JitNeq(result, src1Val, src2Val, src1Var, src2Var, this->func, false /* isStrict */))
|
|
|
{
|
|
|
- // TODO: OOP JIT, const folding
|
|
|
return false;
|
|
|
}
|
|
|
- *result = Js::JavascriptOperators::NotEqual(src1Var, src2Var, this->func->GetScriptContext());
|
|
|
}
|
|
|
break;
|
|
|
case Js::OpCode::BrSrEq_A:
|
|
|
@@ -6702,12 +6795,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
|
|
|
+ if (!Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, this->func, true /* isStrict */))
|
|
|
{
|
|
|
- // TODO: OOP JIT, const folding
|
|
|
return false;
|
|
|
}
|
|
|
- *result = Js::JavascriptOperators::StrictEqual(src1Var, src2Var, this->func->GetScriptContext());
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
@@ -6744,12 +6835,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
|
|
|
+ if (!Op_JitNeq(result, src1Val, src2Val, src1Var, src2Var, this->func, true /* isStrict */))
|
|
|
{
|
|
|
- // TODO: OOP JIT, const folding
|
|
|
return false;
|
|
|
}
|
|
|
- *result = Js::JavascriptOperators::NotStrictEqual(src1Var, src2Var, this->func->GetScriptContext());
|
|
|
}
|
|
|
break;
|
|
|
|