зеркало из https://github.com/mozilla/gecko-dev.git
Bug 838469 - Use CallInfo for inlining natives. r=h4writer
This commit is contained in:
Родитель
93dea27aff
Коммит
1a3e66e87f
|
@ -3370,12 +3370,7 @@ bool
|
||||||
IonBuilder::inlineScriptedCalls(AutoObjectVector &targets, AutoObjectVector &originals,
|
IonBuilder::inlineScriptedCalls(AutoObjectVector &targets, AutoObjectVector &originals,
|
||||||
CallInfo &callInfo)
|
CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
// Add typeInference hints if not set
|
JS_ASSERT(callInfo.hasTypeInfo());
|
||||||
if (!callInfo.hasTypeInfo()) {
|
|
||||||
types::StackTypeSet *barrier;
|
|
||||||
types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
|
|
||||||
callInfo.setTypeInfo(types, barrier);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unwrap the arguments
|
// Unwrap the arguments
|
||||||
JS_ASSERT(callInfo.isWrapped());
|
JS_ASSERT(callInfo.isWrapped());
|
||||||
|
@ -4063,18 +4058,22 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallInfo callInfo(cx, constructing);
|
||||||
|
if (!callInfo.init(current, argc))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
types::StackTypeSet *barrier;
|
||||||
|
types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
|
||||||
|
callInfo.setTypeInfo(types, barrier);
|
||||||
|
|
||||||
// Inline native call.
|
// Inline native call.
|
||||||
if (inliningEnabled() && targets.length() == 1 && targets[0]->toFunction()->isNative()) {
|
if (inliningEnabled() && targets.length() == 1 && targets[0]->toFunction()->isNative()) {
|
||||||
RootedFunction target(cx, targets[0]->toFunction());
|
InliningStatus status = inlineNativeCall(callInfo, targets[0]->toFunction()->native());
|
||||||
InliningStatus status = inlineNativeCall(target->native(), argc, constructing);
|
|
||||||
if (status != InliningStatus_NotInlined)
|
if (status != InliningStatus_NotInlined)
|
||||||
return status != InliningStatus_Error;
|
return status != InliningStatus_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inline scriped call(s).
|
// Inline scriped call(s).
|
||||||
CallInfo callInfo(cx, constructing);
|
|
||||||
if (!callInfo.init(current, argc))
|
|
||||||
return false;
|
|
||||||
if (inliningEnabled() && targets.length() > 0 && makeInliningDecision(targets, argc))
|
if (inliningEnabled() && targets.length() > 0 && makeInliningDecision(targets, argc))
|
||||||
return inlineScriptedCalls(targets, originals, callInfo);
|
return inlineScriptedCalls(targets, originals, callInfo);
|
||||||
|
|
||||||
|
@ -4083,7 +4082,7 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
|
||||||
if (targets.length() == 1)
|
if (targets.length() == 1)
|
||||||
target = targets[0]->toFunction();
|
target = targets[0]->toFunction();
|
||||||
|
|
||||||
return makeCall(target, callInfo, calleeTypes, hasClones);
|
return makeCallBarrier(target, callInfo, calleeTypes, hasClones);
|
||||||
}
|
}
|
||||||
|
|
||||||
MDefinition *
|
MDefinition *
|
||||||
|
|
|
@ -382,41 +382,40 @@ class IonBuilder : public MIRGenerator
|
||||||
};
|
};
|
||||||
|
|
||||||
// Inlining helpers.
|
// Inlining helpers.
|
||||||
bool discardCallArgs(uint32_t argc, MDefinitionVector &argv, MBasicBlock *bb);
|
|
||||||
bool discardCall(uint32_t argc, MDefinitionVector &argv, MBasicBlock *bb);
|
|
||||||
types::StackTypeSet *getInlineReturnTypeSet();
|
types::StackTypeSet *getInlineReturnTypeSet();
|
||||||
MIRType getInlineReturnType();
|
MIRType getInlineReturnType();
|
||||||
types::StackTypeSet *getInlineArgTypeSet(uint32_t argc, uint32_t arg);
|
types::StackTypeSet *getInlineThisTypeSet(CallInfo &callInfo);
|
||||||
MIRType getInlineArgType(uint32_t argc, uint32_t arg);
|
MIRType getInlineThisType(CallInfo &callInfo);
|
||||||
|
types::StackTypeSet *getInlineArgTypeSet(CallInfo &callInfo, uint32_t arg);
|
||||||
|
MIRType getInlineArgType(CallInfo &callInfo, uint32_t arg);
|
||||||
|
|
||||||
// Array natives.
|
// Array natives.
|
||||||
InliningStatus inlineArray(uint32_t argc, bool constructing);
|
InliningStatus inlineArray(CallInfo &callInfo);
|
||||||
InliningStatus inlineArrayPopShift(MArrayPopShift::Mode mode, uint32_t argc, bool constructing);
|
InliningStatus inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode);
|
||||||
InliningStatus inlineArrayPush(uint32_t argc, bool constructing);
|
InliningStatus inlineArrayPush(CallInfo &callInfo);
|
||||||
InliningStatus inlineArrayConcat(uint32_t argc, bool constructing);
|
InliningStatus inlineArrayConcat(CallInfo &callInfo);
|
||||||
|
|
||||||
// Math natives.
|
// Math natives.
|
||||||
InliningStatus inlineMathAbs(uint32_t argc, bool constructing);
|
InliningStatus inlineMathAbs(CallInfo &callInfo);
|
||||||
InliningStatus inlineMathFloor(uint32_t argc, bool constructing);
|
InliningStatus inlineMathFloor(CallInfo &callInfo);
|
||||||
InliningStatus inlineMathRound(uint32_t argc, bool constructing);
|
InliningStatus inlineMathRound(CallInfo &callInfo);
|
||||||
InliningStatus inlineMathSqrt(uint32_t argc, bool constructing);
|
InliningStatus inlineMathSqrt(CallInfo &callInfo);
|
||||||
InliningStatus inlineMathMinMax(bool max, uint32_t argc, bool constructing);
|
InliningStatus inlineMathMinMax(CallInfo &callInfo, bool max);
|
||||||
InliningStatus inlineMathPow(uint32_t argc, bool constructing);
|
InliningStatus inlineMathPow(CallInfo &callInfo);
|
||||||
InliningStatus inlineMathRandom(uint32_t argc, bool constructing);
|
InliningStatus inlineMathRandom(CallInfo &callInfo);
|
||||||
InliningStatus inlineMathImul(uint32_t argc, bool constructing);
|
InliningStatus inlineMathImul(CallInfo &callInfo);
|
||||||
InliningStatus inlineMathFunction(MMathFunction::Function function, uint32_t argc,
|
InliningStatus inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function);
|
||||||
bool constructing);
|
|
||||||
|
|
||||||
// String natives.
|
// String natives.
|
||||||
InliningStatus inlineStringObject(uint32_t argc, bool constructing);
|
InliningStatus inlineStringObject(CallInfo &callInfo);
|
||||||
InliningStatus inlineStrCharCodeAt(uint32_t argc, bool constructing);
|
InliningStatus inlineStrCharCodeAt(CallInfo &callInfo);
|
||||||
InliningStatus inlineStrFromCharCode(uint32_t argc, bool constructing);
|
InliningStatus inlineStrFromCharCode(CallInfo &callInfo);
|
||||||
InliningStatus inlineStrCharAt(uint32_t argc, bool constructing);
|
InliningStatus inlineStrCharAt(CallInfo &callInfo);
|
||||||
|
|
||||||
// RegExp natives.
|
// RegExp natives.
|
||||||
InliningStatus inlineRegExpTest(uint32_t argc, bool constructing);
|
InliningStatus inlineRegExpTest(CallInfo &callInfo);
|
||||||
|
|
||||||
InliningStatus inlineNativeCall(JSNative native, uint32_t argc, bool constructing);
|
InliningStatus inlineNativeCall(CallInfo &callInfo, JSNative native);
|
||||||
|
|
||||||
// Call functions
|
// Call functions
|
||||||
bool jsop_call_inline(HandleFunction callee, CallInfo &callInfo, MBasicBlock *bottom,
|
bool jsop_call_inline(HandleFunction callee, CallInfo &callInfo, MBasicBlock *bottom,
|
||||||
|
|
|
@ -18,105 +18,72 @@ namespace js {
|
||||||
namespace ion {
|
namespace ion {
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineNativeCall(JSNative native, uint32_t argc, bool constructing)
|
IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
|
||||||
{
|
{
|
||||||
// Array natives.
|
// Array natives.
|
||||||
if (native == js_Array)
|
if (native == js_Array)
|
||||||
return inlineArray(argc, constructing);
|
return inlineArray(callInfo);
|
||||||
if (native == js::array_pop)
|
if (native == js::array_pop)
|
||||||
return inlineArrayPopShift(MArrayPopShift::Pop, argc, constructing);
|
return inlineArrayPopShift(callInfo, MArrayPopShift::Pop);
|
||||||
if (native == js::array_shift)
|
if (native == js::array_shift)
|
||||||
return inlineArrayPopShift(MArrayPopShift::Shift, argc, constructing);
|
return inlineArrayPopShift(callInfo, MArrayPopShift::Shift);
|
||||||
if (native == js::array_push)
|
if (native == js::array_push)
|
||||||
return inlineArrayPush(argc, constructing);
|
return inlineArrayPush(callInfo);
|
||||||
if (native == js::array_concat)
|
if (native == js::array_concat)
|
||||||
return inlineArrayConcat(argc, constructing);
|
return inlineArrayConcat(callInfo);
|
||||||
|
|
||||||
// Math natives.
|
// Math natives.
|
||||||
if (native == js_math_abs)
|
if (native == js_math_abs)
|
||||||
return inlineMathAbs(argc, constructing);
|
return inlineMathAbs(callInfo);
|
||||||
if (native == js_math_floor)
|
if (native == js_math_floor)
|
||||||
return inlineMathFloor(argc, constructing);
|
return inlineMathFloor(callInfo);
|
||||||
if (native == js_math_round)
|
if (native == js_math_round)
|
||||||
return inlineMathRound(argc, constructing);
|
return inlineMathRound(callInfo);
|
||||||
if (native == js_math_sqrt)
|
if (native == js_math_sqrt)
|
||||||
return inlineMathSqrt(argc, constructing);
|
return inlineMathSqrt(callInfo);
|
||||||
if (native == js_math_max)
|
if (native == js_math_max)
|
||||||
return inlineMathMinMax(true /* max */, argc, constructing);
|
return inlineMathMinMax(callInfo, true /* max */);
|
||||||
if (native == js_math_min)
|
if (native == js_math_min)
|
||||||
return inlineMathMinMax(false /* max */, argc, constructing);
|
return inlineMathMinMax(callInfo, false /* max */);
|
||||||
if (native == js_math_pow)
|
if (native == js_math_pow)
|
||||||
return inlineMathPow(argc, constructing);
|
return inlineMathPow(callInfo);
|
||||||
if (native == js_math_random)
|
if (native == js_math_random)
|
||||||
return inlineMathRandom(argc, constructing);
|
return inlineMathRandom(callInfo);
|
||||||
if (native == js::math_imul)
|
if (native == js::math_imul)
|
||||||
return inlineMathImul(argc, constructing);
|
return inlineMathImul(callInfo);
|
||||||
if (native == js::math_sin)
|
if (native == js::math_sin)
|
||||||
return inlineMathFunction(MMathFunction::Sin, argc, constructing);
|
return inlineMathFunction(callInfo, MMathFunction::Sin);
|
||||||
if (native == js::math_cos)
|
if (native == js::math_cos)
|
||||||
return inlineMathFunction(MMathFunction::Cos, argc, constructing);
|
return inlineMathFunction(callInfo, MMathFunction::Cos);
|
||||||
if (native == js::math_tan)
|
if (native == js::math_tan)
|
||||||
return inlineMathFunction(MMathFunction::Tan, argc, constructing);
|
return inlineMathFunction(callInfo, MMathFunction::Tan);
|
||||||
if (native == js::math_log)
|
if (native == js::math_log)
|
||||||
return inlineMathFunction(MMathFunction::Log, argc, constructing);
|
return inlineMathFunction(callInfo, MMathFunction::Log);
|
||||||
|
|
||||||
// String natives.
|
// String natives.
|
||||||
if (native == js_String)
|
if (native == js_String)
|
||||||
return inlineStringObject(argc, constructing);
|
return inlineStringObject(callInfo);
|
||||||
if (native == js_str_charCodeAt)
|
if (native == js_str_charCodeAt)
|
||||||
return inlineStrCharCodeAt(argc, constructing);
|
return inlineStrCharCodeAt(callInfo);
|
||||||
if (native == js::str_fromCharCode)
|
if (native == js::str_fromCharCode)
|
||||||
return inlineStrFromCharCode(argc, constructing);
|
return inlineStrFromCharCode(callInfo);
|
||||||
if (native == js_str_charAt)
|
if (native == js_str_charAt)
|
||||||
return inlineStrCharAt(argc, constructing);
|
return inlineStrCharAt(callInfo);
|
||||||
|
|
||||||
// RegExp natives.
|
// RegExp natives.
|
||||||
if (native == regexp_exec && !CallResultEscapes(pc))
|
if (native == regexp_exec && !CallResultEscapes(pc))
|
||||||
return inlineRegExpTest(argc, constructing);
|
return inlineRegExpTest(callInfo);
|
||||||
if (native == regexp_test)
|
if (native == regexp_test)
|
||||||
return inlineRegExpTest(argc, constructing);
|
return inlineRegExpTest(callInfo);
|
||||||
|
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
IonBuilder::discardCallArgs(uint32_t argc, MDefinitionVector &argv, MBasicBlock *bb)
|
|
||||||
{
|
|
||||||
if (!argv.resizeUninitialized(argc + 1))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (int32_t i = argc; i >= 0; i--) {
|
|
||||||
// Unwrap each MPassArg, replacing it with its contents.
|
|
||||||
MPassArg *passArg = bb->pop()->toPassArg();
|
|
||||||
MBasicBlock *block = passArg->block();
|
|
||||||
MDefinition *wrapped = passArg->getArgument();
|
|
||||||
passArg->replaceAllUsesWith(wrapped);
|
|
||||||
block->discard(passArg);
|
|
||||||
|
|
||||||
// Remember contents in vector.
|
|
||||||
argv[i] = wrapped;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
IonBuilder::discardCall(uint32_t argc, MDefinitionVector &argv, MBasicBlock *bb)
|
|
||||||
{
|
|
||||||
if (!discardCallArgs(argc, argv, bb))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Function MDefinition implicitly consumed by inlining.
|
|
||||||
bb->pop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
types::StackTypeSet *
|
types::StackTypeSet *
|
||||||
IonBuilder::getInlineReturnTypeSet()
|
IonBuilder::getInlineReturnTypeSet()
|
||||||
{
|
{
|
||||||
types::StackTypeSet *barrier;
|
types::StackTypeSet *barrier;
|
||||||
types::StackTypeSet *returnTypes = oracle->returnTypeSet(script(), pc, &barrier);
|
types::StackTypeSet *returnTypes = oracle->returnTypeSet(script(), pc, &barrier);
|
||||||
|
|
||||||
JS_ASSERT(returnTypes);
|
JS_ASSERT(returnTypes);
|
||||||
return returnTypes;
|
return returnTypes;
|
||||||
}
|
}
|
||||||
|
@ -129,65 +96,78 @@ IonBuilder::getInlineReturnType()
|
||||||
}
|
}
|
||||||
|
|
||||||
types::StackTypeSet *
|
types::StackTypeSet *
|
||||||
IonBuilder::getInlineArgTypeSet(uint32_t argc, uint32_t arg)
|
IonBuilder::getInlineThisTypeSet(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
types::StackTypeSet *argTypes = oracle->getCallArg(script(), argc, arg, pc);
|
types::StackTypeSet *thisTypes = oracle->getCallArg(script(), callInfo.argc(), 0, pc);
|
||||||
|
JS_ASSERT(thisTypes);
|
||||||
|
return thisTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
MIRType
|
||||||
|
IonBuilder::getInlineThisType(CallInfo &callInfo)
|
||||||
|
{
|
||||||
|
types::StackTypeSet *argTypes = getInlineThisTypeSet(callInfo);
|
||||||
|
return MIRTypeFromValueType(argTypes->getKnownTypeTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
types::StackTypeSet *
|
||||||
|
IonBuilder::getInlineArgTypeSet(CallInfo &callInfo, uint32_t arg)
|
||||||
|
{
|
||||||
|
types::StackTypeSet *argTypes = oracle->getCallArg(script(), callInfo.argc(), arg + 1, pc);
|
||||||
JS_ASSERT(argTypes);
|
JS_ASSERT(argTypes);
|
||||||
return argTypes;
|
return argTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
MIRType
|
MIRType
|
||||||
IonBuilder::getInlineArgType(uint32_t argc, uint32_t arg)
|
IonBuilder::getInlineArgType(CallInfo &callInfo, uint32_t arg)
|
||||||
{
|
{
|
||||||
types::StackTypeSet *argTypes = getInlineArgTypeSet(argc, arg);
|
types::StackTypeSet *argTypes = getInlineArgTypeSet(callInfo, arg);
|
||||||
return MIRTypeFromValueType(argTypes->getKnownTypeTag());
|
return MIRTypeFromValueType(argTypes->getKnownTypeTag());
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathFunction(MMathFunction::Function function, uint32_t argc, bool constructing)
|
IonBuilder::inlineMathFunction(CallInfo &callInfo, MMathFunction::Function function)
|
||||||
{
|
{
|
||||||
if (constructing)
|
if (callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (argc != 1)
|
if (callInfo.argc() != 1)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (getInlineReturnType() != MIRType_Double)
|
if (getInlineReturnType() != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (!IsNumberType(getInlineArgType(argc, 1)))
|
if (!IsNumberType(getInlineArgType(callInfo, 0)))
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MathCache *cache = cx->runtime->getMathCache(cx);
|
MathCache *cache = cx->runtime->getMathCache(cx);
|
||||||
if (!cache)
|
if (!cache)
|
||||||
return InliningStatus_Error;
|
return InliningStatus_Error;
|
||||||
|
|
||||||
MMathFunction *ins = MMathFunction::New(argv[1], function, cache);
|
MMathFunction *ins = MMathFunction::New(callInfo.getArg(0), function, cache);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineArray(uint32_t argc, bool constructing)
|
IonBuilder::inlineArray(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
uint32_t initLength = 0;
|
uint32_t initLength = 0;
|
||||||
MNewArray::AllocatingBehaviour allocating = MNewArray::NewArray_Unallocating;
|
MNewArray::AllocatingBehaviour allocating = MNewArray::NewArray_Unallocating;
|
||||||
|
|
||||||
// Multiple arguments imply array initialization, not just construction.
|
// Multiple arguments imply array initialization, not just construction.
|
||||||
if (argc >= 2) {
|
if (callInfo.argc() >= 2) {
|
||||||
initLength = argc;
|
initLength = callInfo.argc();
|
||||||
allocating = MNewArray::NewArray_Allocating;
|
allocating = MNewArray::NewArray_Allocating;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A single integer argument denotes initial length.
|
// A single integer argument denotes initial length.
|
||||||
if (argc == 1) {
|
if (callInfo.argc() == 1) {
|
||||||
if (getInlineArgType(argc, 1) != MIRType_Int32)
|
if (getInlineArgType(callInfo, 0) != MIRType_Int32)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
MDefinition *arg = current->peek(-1)->toPassArg()->getArgument();
|
MDefinition *arg = callInfo.getArg(0)->toPassArg()->getArgument();
|
||||||
if (!arg->isConstant())
|
if (!arg->isConstant())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
|
@ -197,9 +177,7 @@ IonBuilder::inlineArray(uint32_t argc, bool constructing)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
JSObject *templateObject = getNewArrayTemplateObject(initLength);
|
JSObject *templateObject = getNewArrayTemplateObject(initLength);
|
||||||
if (!templateObject)
|
if (!templateObject)
|
||||||
|
@ -213,7 +191,7 @@ IonBuilder::inlineArray(uint32_t argc, bool constructing)
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
|
|
||||||
if (argc >= 2) {
|
if (callInfo.argc() >= 2) {
|
||||||
// Get the elements vector.
|
// Get the elements vector.
|
||||||
MElements *elements = MElements::New(ins);
|
MElements *elements = MElements::New(ins);
|
||||||
current->add(elements);
|
current->add(elements);
|
||||||
|
@ -226,7 +204,7 @@ IonBuilder::inlineArray(uint32_t argc, bool constructing)
|
||||||
id = MConstant::New(Int32Value(i));
|
id = MConstant::New(Int32Value(i));
|
||||||
current->add(id);
|
current->add(id);
|
||||||
|
|
||||||
MDefinition *value = argv[i + 1];
|
MDefinition *value = callInfo.getArg(i);
|
||||||
if (convertDoubles) {
|
if (convertDoubles) {
|
||||||
MInstruction *valueDouble = MToDouble::New(value);
|
MInstruction *valueDouble = MToDouble::New(value);
|
||||||
current->add(valueDouble);
|
current->add(valueDouble);
|
||||||
|
@ -250,15 +228,15 @@ IonBuilder::inlineArray(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineArrayPopShift(MArrayPopShift::Mode mode, uint32_t argc, bool constructing)
|
IonBuilder::inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode)
|
||||||
{
|
{
|
||||||
if (constructing)
|
if (callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType returnType = getInlineReturnType();
|
MIRType returnType = getInlineReturnType();
|
||||||
if (returnType == MIRType_Undefined || returnType == MIRType_Null)
|
if (returnType == MIRType_Undefined || returnType == MIRType_Null)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (getInlineArgType(argc, 0) != MIRType_Object)
|
if (getInlineThisType(callInfo) != MIRType_Object)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
// Pop and shift are only handled for dense arrays that have never been
|
// Pop and shift are only handled for dense arrays that have never been
|
||||||
|
@ -272,7 +250,7 @@ IonBuilder::inlineArrayPopShift(MArrayPopShift::Mode mode, uint32_t argc, bool c
|
||||||
types::OBJECT_FLAG_LENGTH_OVERFLOW |
|
types::OBJECT_FLAG_LENGTH_OVERFLOW |
|
||||||
types::OBJECT_FLAG_ITERATED;
|
types::OBJECT_FLAG_ITERATED;
|
||||||
|
|
||||||
types::StackTypeSet *thisTypes = getInlineArgTypeSet(argc, 0);
|
types::StackTypeSet *thisTypes = getInlineThisTypeSet(callInfo);
|
||||||
if (thisTypes->getKnownClass() != &ArrayClass)
|
if (thisTypes->getKnownClass() != &ArrayClass)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (thisTypes->hasObjectFlags(cx, unhandledFlags))
|
if (thisTypes->hasObjectFlags(cx, unhandledFlags))
|
||||||
|
@ -281,15 +259,14 @@ IonBuilder::inlineArrayPopShift(MArrayPopShift::Mode mode, uint32_t argc, bool c
|
||||||
if (types::ArrayPrototypeHasIndexedProperty(cx, script))
|
if (types::ArrayPrototypeHasIndexedProperty(cx, script))
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
types::StackTypeSet *returnTypes = getInlineReturnTypeSet();
|
types::StackTypeSet *returnTypes = getInlineReturnTypeSet();
|
||||||
bool needsHoleCheck = thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED);
|
bool needsHoleCheck = thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED);
|
||||||
bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
|
bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
|
||||||
|
|
||||||
MArrayPopShift *ins = MArrayPopShift::New(argv[0], mode, needsHoleCheck, maybeUndefined);
|
MArrayPopShift *ins = MArrayPopShift::New(callInfo.thisArg(), mode,
|
||||||
|
needsHoleCheck, maybeUndefined);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
ins->setResultType(returnType);
|
ins->setResultType(returnType);
|
||||||
|
@ -300,19 +277,19 @@ IonBuilder::inlineArrayPopShift(MArrayPopShift::Mode mode, uint32_t argc, bool c
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineArrayPush(uint32_t argc, bool constructing)
|
IonBuilder::inlineArrayPush(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (argc != 1 || constructing)
|
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (getInlineReturnType() != MIRType_Int32)
|
if (getInlineReturnType() != MIRType_Int32)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (getInlineArgType(argc, 0) != MIRType_Object)
|
if (getInlineThisType(callInfo) != MIRType_Object)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
// Inference's TypeConstraintCall generates the constraints that propagate
|
// Inference's TypeConstraintCall generates the constraints that propagate
|
||||||
// properties directly into the result type set.
|
// properties directly into the result type set.
|
||||||
types::StackTypeSet *thisTypes = getInlineArgTypeSet(argc, 0);
|
types::StackTypeSet *thisTypes = getInlineThisTypeSet(callInfo);
|
||||||
if (thisTypes->getKnownClass() != &ArrayClass)
|
if (thisTypes->getKnownClass() != &ArrayClass)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES |
|
if (thisTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPARSE_INDEXES |
|
||||||
|
@ -328,11 +305,9 @@ IonBuilder::inlineArrayPush(uint32_t argc, bool constructing)
|
||||||
if (conversion == types::StackTypeSet::AmbiguousDoubleConversion)
|
if (conversion == types::StackTypeSet::AmbiguousDoubleConversion)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MDefinition *value = argv[1];
|
MDefinition *value = callInfo.getArg(0);
|
||||||
if (conversion == types::StackTypeSet::AlwaysConvertToDoubles ||
|
if (conversion == types::StackTypeSet::AlwaysConvertToDoubles ||
|
||||||
conversion == types::StackTypeSet::MaybeConvertToDoubles)
|
conversion == types::StackTypeSet::MaybeConvertToDoubles)
|
||||||
{
|
{
|
||||||
|
@ -341,7 +316,7 @@ IonBuilder::inlineArrayPush(uint32_t argc, bool constructing)
|
||||||
value = valueDouble;
|
value = valueDouble;
|
||||||
}
|
}
|
||||||
|
|
||||||
MArrayPush *ins = MArrayPush::New(argv[0], value);
|
MArrayPush *ins = MArrayPush::New(callInfo.thisArg(), value);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
|
|
||||||
|
@ -351,22 +326,22 @@ IonBuilder::inlineArrayPush(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineArrayConcat(uint32_t argc, bool constructing)
|
IonBuilder::inlineArrayConcat(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (argc != 1 || constructing)
|
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
// Ensure |this|, argument and result are objects.
|
// Ensure |this|, argument and result are objects.
|
||||||
if (getInlineReturnType() != MIRType_Object)
|
if (getInlineReturnType() != MIRType_Object)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (getInlineArgType(argc, 0) != MIRType_Object)
|
if (getInlineThisType(callInfo) != MIRType_Object)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (getInlineArgType(argc, 1) != MIRType_Object)
|
if (getInlineArgType(callInfo, 0) != MIRType_Object)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
// |this| and the argument must be dense arrays.
|
// |this| and the argument must be dense arrays.
|
||||||
types::StackTypeSet *thisTypes = getInlineArgTypeSet(argc, 0);
|
types::StackTypeSet *thisTypes = getInlineThisTypeSet(callInfo);
|
||||||
types::StackTypeSet *argTypes = getInlineArgTypeSet(argc, 1);
|
types::StackTypeSet *argTypes = getInlineArgTypeSet(callInfo, 0);
|
||||||
|
|
||||||
if (thisTypes->getKnownClass() != &ArrayClass)
|
if (thisTypes->getKnownClass() != &ArrayClass)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
@ -431,11 +406,9 @@ IonBuilder::inlineArrayConcat(uint32_t argc, bool constructing)
|
||||||
return InliningStatus_Error;
|
return InliningStatus_Error;
|
||||||
templateObj->setType(thisType);
|
templateObj->setType(thisType);
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MArrayConcat *ins = MArrayConcat::New(argv[0], argv[1], templateObj);
|
MArrayConcat *ins = MArrayConcat::New(callInfo.thisArg(), callInfo.getArg(0), templateObj);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
|
|
||||||
|
@ -445,26 +418,24 @@ IonBuilder::inlineArrayConcat(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathAbs(uint32_t argc, bool constructing)
|
IonBuilder::inlineMathAbs(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (constructing)
|
if (callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (argc != 1)
|
if (callInfo.argc() != 1)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType returnType = getInlineReturnType();
|
MIRType returnType = getInlineReturnType();
|
||||||
MIRType argType = getInlineArgType(argc, 1);
|
MIRType argType = getInlineArgType(callInfo, 0);
|
||||||
if (argType != MIRType_Int32 && argType != MIRType_Double)
|
if (argType != MIRType_Int32 && argType != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (argType != returnType)
|
if (argType != returnType)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MAbs *ins = MAbs::New(argv[1], returnType);
|
MAbs *ins = MAbs::New(callInfo.getArg(0), returnType);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
|
|
||||||
|
@ -472,33 +443,29 @@ IonBuilder::inlineMathAbs(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathFloor(uint32_t argc, bool constructing)
|
IonBuilder::inlineMathFloor(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (constructing)
|
if (callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (argc != 1)
|
if (callInfo.argc() != 1)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType argType = getInlineArgType(argc, 1);
|
MIRType argType = getInlineArgType(callInfo, 0);
|
||||||
if (getInlineReturnType() != MIRType_Int32)
|
if (getInlineReturnType() != MIRType_Int32)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
// Math.floor(int(x)) == int(x)
|
// Math.floor(int(x)) == int(x)
|
||||||
if (argType == MIRType_Int32) {
|
if (argType == MIRType_Int32) {
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
current->push(callInfo.getArg(0));
|
||||||
return InliningStatus_Error;
|
|
||||||
current->push(argv[1]);
|
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argType == MIRType_Double) {
|
if (argType == MIRType_Double) {
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
MFloor *ins = new MFloor(callInfo.getArg(0));
|
||||||
return InliningStatus_Error;
|
|
||||||
MFloor *ins = new MFloor(argv[1]);
|
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
|
@ -508,31 +475,27 @@ IonBuilder::inlineMathFloor(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathRound(uint32_t argc, bool constructing)
|
IonBuilder::inlineMathRound(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (constructing)
|
if (callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (argc != 1)
|
if (callInfo.argc() != 1)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType returnType = getInlineReturnType();
|
MIRType returnType = getInlineReturnType();
|
||||||
MIRType argType = getInlineArgType(argc, 1);
|
MIRType argType = getInlineArgType(callInfo, 0);
|
||||||
|
|
||||||
// Math.round(int(x)) == int(x)
|
// Math.round(int(x)) == int(x)
|
||||||
if (argType == MIRType_Int32 && returnType == MIRType_Int32) {
|
if (argType == MIRType_Int32 && returnType == MIRType_Int32) {
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
current->push(callInfo.getArg(0));
|
||||||
return InliningStatus_Error;
|
|
||||||
current->push(argv[1]);
|
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argType == MIRType_Double && returnType == MIRType_Int32) {
|
if (argType == MIRType_Double && returnType == MIRType_Int32) {
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
MRound *ins = new MRound(callInfo.getArg(0));
|
||||||
return InliningStatus_Error;
|
|
||||||
MRound *ins = new MRound(argv[1]);
|
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
|
@ -542,72 +505,71 @@ IonBuilder::inlineMathRound(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathSqrt(uint32_t argc, bool constructing)
|
IonBuilder::inlineMathSqrt(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (constructing)
|
if (callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (argc != 1)
|
if (callInfo.argc() != 1)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType argType = getInlineArgType(argc, 1);
|
MIRType argType = getInlineArgType(callInfo, 0);
|
||||||
if (getInlineReturnType() != MIRType_Double)
|
if (getInlineReturnType() != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (argType != MIRType_Double && argType != MIRType_Int32)
|
if (argType != MIRType_Double && argType != MIRType_Int32)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MSqrt *sqrt = MSqrt::New(argv[1]);
|
MSqrt *sqrt = MSqrt::New(callInfo.getArg(0));
|
||||||
current->add(sqrt);
|
current->add(sqrt);
|
||||||
current->push(sqrt);
|
current->push(sqrt);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathPow(uint32_t argc, bool constructing)
|
IonBuilder::inlineMathPow(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (constructing)
|
if (callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (argc != 2)
|
if (callInfo.argc() != 2)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
// Typechecking.
|
// Typechecking.
|
||||||
if (getInlineReturnType() != MIRType_Double)
|
if (getInlineReturnType() != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType arg1Type = getInlineArgType(argc, 1);
|
MIRType baseType = getInlineArgType(callInfo, 0);
|
||||||
MIRType arg2Type = getInlineArgType(argc, 2);
|
MIRType powerType = getInlineArgType(callInfo, 1);
|
||||||
|
|
||||||
if (arg1Type != MIRType_Int32 && arg1Type != MIRType_Double)
|
if (baseType != MIRType_Int32 && baseType != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (arg2Type != MIRType_Int32 && arg2Type != MIRType_Double)
|
if (powerType != MIRType_Int32 && powerType != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
// If the non-power input is integer, convert it to a Double.
|
MDefinition *base = callInfo.getArg(0);
|
||||||
|
MDefinition *power = callInfo.getArg(1);
|
||||||
|
|
||||||
|
// If the base is integer, convert it to a Double.
|
||||||
// Safe since the output must be a Double.
|
// Safe since the output must be a Double.
|
||||||
if (arg1Type == MIRType_Int32) {
|
if (baseType == MIRType_Int32) {
|
||||||
MToDouble *conv = MToDouble::New(argv[1]);
|
MToDouble *conv = MToDouble::New(base);
|
||||||
current->add(conv);
|
current->add(conv);
|
||||||
argv[1] = conv;
|
base = conv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimize some constant powers.
|
// Optimize some constant powers.
|
||||||
if (argv[2]->isConstant()) {
|
if (callInfo.getArg(1)->isConstant()) {
|
||||||
double pow;
|
double pow;
|
||||||
if (!ToNumber(GetIonContext()->cx, argv[2]->toConstant()->value(), &pow))
|
if (!ToNumber(GetIonContext()->cx, callInfo.getArg(1)->toConstant()->value(), &pow))
|
||||||
return InliningStatus_Error;
|
return InliningStatus_Error;
|
||||||
|
|
||||||
// Math.pow(x, 0.5) is a sqrt with edge-case detection.
|
// Math.pow(x, 0.5) is a sqrt with edge-case detection.
|
||||||
if (pow == 0.5) {
|
if (pow == 0.5) {
|
||||||
MPowHalf *half = MPowHalf::New(argv[1]);
|
MPowHalf *half = MPowHalf::New(base);
|
||||||
current->add(half);
|
current->add(half);
|
||||||
current->push(half);
|
current->push(half);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
|
@ -615,7 +577,7 @@ IonBuilder::inlineMathPow(uint32_t argc, bool constructing)
|
||||||
|
|
||||||
// Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5), even for edge cases.
|
// Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5), even for edge cases.
|
||||||
if (pow == -0.5) {
|
if (pow == -0.5) {
|
||||||
MPowHalf *half = MPowHalf::New(argv[1]);
|
MPowHalf *half = MPowHalf::New(base);
|
||||||
current->add(half);
|
current->add(half);
|
||||||
MConstant *one = MConstant::New(DoubleValue(1.0));
|
MConstant *one = MConstant::New(DoubleValue(1.0));
|
||||||
current->add(one);
|
current->add(one);
|
||||||
|
@ -627,13 +589,13 @@ IonBuilder::inlineMathPow(uint32_t argc, bool constructing)
|
||||||
|
|
||||||
// Math.pow(x, 1) == x.
|
// Math.pow(x, 1) == x.
|
||||||
if (pow == 1.0) {
|
if (pow == 1.0) {
|
||||||
current->push(argv[1]);
|
current->push(base);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Math.pow(x, 2) == x*x.
|
// Math.pow(x, 2) == x*x.
|
||||||
if (pow == 2.0) {
|
if (pow == 2.0) {
|
||||||
MMul *mul = MMul::New(argv[1], argv[1], MIRType_Double);
|
MMul *mul = MMul::New(base, base, MIRType_Double);
|
||||||
current->add(mul);
|
current->add(mul);
|
||||||
current->push(mul);
|
current->push(mul);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
|
@ -641,9 +603,9 @@ IonBuilder::inlineMathPow(uint32_t argc, bool constructing)
|
||||||
|
|
||||||
// Math.pow(x, 3) == x*x*x.
|
// Math.pow(x, 3) == x*x*x.
|
||||||
if (pow == 3.0) {
|
if (pow == 3.0) {
|
||||||
MMul *mul1 = MMul::New(argv[1], argv[1], MIRType_Double);
|
MMul *mul1 = MMul::New(base, base, MIRType_Double);
|
||||||
current->add(mul1);
|
current->add(mul1);
|
||||||
MMul *mul2 = MMul::New(argv[1], mul1, MIRType_Double);
|
MMul *mul2 = MMul::New(base, mul1, MIRType_Double);
|
||||||
current->add(mul2);
|
current->add(mul2);
|
||||||
current->push(mul2);
|
current->push(mul2);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
|
@ -651,7 +613,7 @@ IonBuilder::inlineMathPow(uint32_t argc, bool constructing)
|
||||||
|
|
||||||
// Math.pow(x, 4) == y*y, where y = x*x.
|
// Math.pow(x, 4) == y*y, where y = x*x.
|
||||||
if (pow == 4.0) {
|
if (pow == 4.0) {
|
||||||
MMul *y = MMul::New(argv[1], argv[1], MIRType_Double);
|
MMul *y = MMul::New(base, base, MIRType_Double);
|
||||||
current->add(y);
|
current->add(y);
|
||||||
MMul *mul = MMul::New(y, y, MIRType_Double);
|
MMul *mul = MMul::New(y, y, MIRType_Double);
|
||||||
current->add(mul);
|
current->add(mul);
|
||||||
|
@ -660,24 +622,22 @@ IonBuilder::inlineMathPow(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MPow *ins = MPow::New(argv[1], argv[2], arg2Type);
|
MPow *ins = MPow::New(base, power, powerType);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathRandom(uint32_t argc, bool constructing)
|
IonBuilder::inlineMathRandom(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (constructing)
|
if (callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (getInlineReturnType() != MIRType_Double)
|
if (getInlineReturnType() != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MRandom *rand = MRandom::New();
|
MRandom *rand = MRandom::New();
|
||||||
current->add(rand);
|
current->add(rand);
|
||||||
|
@ -686,28 +646,26 @@ IonBuilder::inlineMathRandom(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathImul(uint32_t argc, bool constructing)
|
IonBuilder::inlineMathImul(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (argc != 2 || constructing)
|
if (callInfo.argc() != 2 || callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType returnType = getInlineReturnType();
|
MIRType returnType = getInlineReturnType();
|
||||||
if (returnType != MIRType_Int32)
|
if (returnType != MIRType_Int32)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (!IsNumberType(getInlineArgType(argc, 1)))
|
if (!IsNumberType(getInlineArgType(callInfo, 0)))
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (!IsNumberType(getInlineArgType(argc, 2)))
|
if (!IsNumberType(getInlineArgType(callInfo, 1)))
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MInstruction *first = MTruncateToInt32::New(argv[1]);
|
MInstruction *first = MTruncateToInt32::New(callInfo.getArg(0));
|
||||||
current->add(first);
|
current->add(first);
|
||||||
|
|
||||||
MInstruction *second = MTruncateToInt32::New(argv[2]);
|
MInstruction *second = MTruncateToInt32::New(callInfo.getArg(1));
|
||||||
current->add(second);
|
current->add(second);
|
||||||
|
|
||||||
MMul *ins = MMul::New(first, second, MIRType_Int32, MMul::Integer);
|
MMul *ins = MMul::New(first, second, MIRType_Int32, MMul::Integer);
|
||||||
|
@ -717,60 +675,56 @@ IonBuilder::inlineMathImul(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineMathMinMax(bool max, uint32_t argc, bool constructing)
|
IonBuilder::inlineMathMinMax(CallInfo &callInfo, bool max)
|
||||||
{
|
{
|
||||||
if (argc != 2 || constructing)
|
if (callInfo.argc() != 2 || callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType returnType = getInlineReturnType();
|
MIRType returnType = getInlineReturnType();
|
||||||
if (!IsNumberType(returnType))
|
if (!IsNumberType(returnType))
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MIRType arg1Type = getInlineArgType(argc, 1);
|
MIRType arg0Type = getInlineArgType(callInfo, 0);
|
||||||
if (!IsNumberType(arg1Type))
|
if (!IsNumberType(arg0Type))
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
MIRType arg2Type = getInlineArgType(argc, 2);
|
MIRType arg1Type = getInlineArgType(callInfo, 1);
|
||||||
if (!IsNumberType(arg2Type))
|
if (!IsNumberType(arg1Type))
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (returnType == MIRType_Int32 &&
|
if (returnType == MIRType_Int32 &&
|
||||||
(arg1Type == MIRType_Double || arg2Type == MIRType_Double))
|
(arg0Type == MIRType_Double || arg1Type == MIRType_Double))
|
||||||
{
|
{
|
||||||
// We would need to inform TI, if we happen to return a double.
|
// We would need to inform TI, if we happen to return a double.
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MMinMax *ins = MMinMax::New(argv[1], argv[2], returnType, max);
|
MMinMax *ins = MMinMax::New(callInfo.getArg(0), callInfo.getArg(1), returnType, max);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineStringObject(uint32_t argc, bool constructing)
|
IonBuilder::inlineStringObject(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (argc != 1 || !constructing)
|
if (callInfo.argc() != 1 || !callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
// MToString only supports int32 or string values.
|
// MToString only supports int32 or string values.
|
||||||
MIRType type = getInlineArgType(argc, 1);
|
MIRType type = getInlineArgType(callInfo, 0);
|
||||||
if (type != MIRType_Int32 && type != MIRType_String)
|
if (type != MIRType_Int32 && type != MIRType_String)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
RootedString emptyString(cx, cx->runtime->emptyString);
|
RootedString emptyString(cx, cx->runtime->emptyString);
|
||||||
RootedObject templateObj(cx, StringObject::create(cx, emptyString));
|
RootedObject templateObj(cx, StringObject::create(cx, emptyString));
|
||||||
if (!templateObj)
|
if (!templateObj)
|
||||||
return InliningStatus_Error;
|
return InliningStatus_Error;
|
||||||
|
|
||||||
MNewStringObject *ins = MNewStringObject::New(argv[1], templateObj);
|
MNewStringObject *ins = MNewStringObject::New(callInfo.getArg(0), templateObj);
|
||||||
current->add(ins);
|
current->add(ins);
|
||||||
current->push(ins);
|
current->push(ins);
|
||||||
|
|
||||||
|
@ -781,53 +735,49 @@ IonBuilder::inlineStringObject(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineStrCharCodeAt(uint32_t argc, bool constructing)
|
IonBuilder::inlineStrCharCodeAt(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (argc != 1 || constructing)
|
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (getInlineReturnType() != MIRType_Int32)
|
if (getInlineReturnType() != MIRType_Int32)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (getInlineArgType(argc, 0) != MIRType_String)
|
if (getInlineThisType(callInfo) != MIRType_String)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
MIRType argType = getInlineArgType(argc, 1);
|
MIRType argType = getInlineArgType(callInfo, 0);
|
||||||
if (argType != MIRType_Int32 && argType != MIRType_Double)
|
if (argType != MIRType_Int32 && argType != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MInstruction *index = MToInt32::New(argv[1]);
|
MInstruction *index = MToInt32::New(callInfo.getArg(0));
|
||||||
current->add(index);
|
current->add(index);
|
||||||
|
|
||||||
MStringLength *length = MStringLength::New(argv[0]);
|
MStringLength *length = MStringLength::New(callInfo.thisArg());
|
||||||
current->add(length);
|
current->add(length);
|
||||||
|
|
||||||
index = addBoundsCheck(index, length);
|
index = addBoundsCheck(index, length);
|
||||||
|
|
||||||
MCharCodeAt *charCode = MCharCodeAt::New(argv[0], index);
|
MCharCodeAt *charCode = MCharCodeAt::New(callInfo.thisArg(), index);
|
||||||
current->add(charCode);
|
current->add(charCode);
|
||||||
current->push(charCode);
|
current->push(charCode);
|
||||||
return InliningStatus_Inlined;
|
return InliningStatus_Inlined;
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineStrFromCharCode(uint32_t argc, bool constructing)
|
IonBuilder::inlineStrFromCharCode(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (argc != 1 || constructing)
|
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (getInlineReturnType() != MIRType_String)
|
if (getInlineReturnType() != MIRType_String)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (getInlineArgType(argc, 1) != MIRType_Int32)
|
if (getInlineArgType(callInfo, 0) != MIRType_Int32)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MToInt32 *charCode = MToInt32::New(argv[1]);
|
MToInt32 *charCode = MToInt32::New(callInfo.getArg(0));
|
||||||
current->add(charCode);
|
current->add(charCode);
|
||||||
|
|
||||||
MFromCharCode *string = MFromCharCode::New(charCode);
|
MFromCharCode *string = MFromCharCode::New(charCode);
|
||||||
|
@ -837,33 +787,31 @@ IonBuilder::inlineStrFromCharCode(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineStrCharAt(uint32_t argc, bool constructing)
|
IonBuilder::inlineStrCharAt(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (argc != 1 || constructing)
|
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (getInlineReturnType() != MIRType_String)
|
if (getInlineReturnType() != MIRType_String)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (getInlineArgType(argc, 0) != MIRType_String)
|
if (getInlineThisType(callInfo) != MIRType_String)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
MIRType argType = getInlineArgType(argc, 1);
|
MIRType argType = getInlineArgType(callInfo, 0);
|
||||||
if (argType != MIRType_Int32 && argType != MIRType_Double)
|
if (argType != MIRType_Int32 && argType != MIRType_Double)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MInstruction *index = MToInt32::New(argv[1]);
|
MInstruction *index = MToInt32::New(callInfo.getArg(0));
|
||||||
current->add(index);
|
current->add(index);
|
||||||
|
|
||||||
MStringLength *length = MStringLength::New(argv[0]);
|
MStringLength *length = MStringLength::New(callInfo.thisArg());
|
||||||
current->add(length);
|
current->add(length);
|
||||||
|
|
||||||
index = addBoundsCheck(index, length);
|
index = addBoundsCheck(index, length);
|
||||||
|
|
||||||
// String.charAt(x) = String.fromCharCode(String.charCodeAt(x))
|
// String.charAt(x) = String.fromCharCode(String.charCodeAt(x))
|
||||||
MCharCodeAt *charCode = MCharCodeAt::New(argv[0], index);
|
MCharCodeAt *charCode = MCharCodeAt::New(callInfo.thisArg(), index);
|
||||||
current->add(charCode);
|
current->add(charCode);
|
||||||
|
|
||||||
MFromCharCode *string = MFromCharCode::New(charCode);
|
MFromCharCode *string = MFromCharCode::New(charCode);
|
||||||
|
@ -873,25 +821,23 @@ IonBuilder::inlineStrCharAt(uint32_t argc, bool constructing)
|
||||||
}
|
}
|
||||||
|
|
||||||
IonBuilder::InliningStatus
|
IonBuilder::InliningStatus
|
||||||
IonBuilder::inlineRegExpTest(uint32_t argc, bool constructing)
|
IonBuilder::inlineRegExpTest(CallInfo &callInfo)
|
||||||
{
|
{
|
||||||
if (argc != 1 || constructing)
|
if (callInfo.argc() != 1 || callInfo.constructing())
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
// TI can infer a NULL return type of regexp_test with eager compilation.
|
// TI can infer a NULL return type of regexp_test with eager compilation.
|
||||||
if (CallResultEscapes(pc) && getInlineReturnType() != MIRType_Boolean)
|
if (CallResultEscapes(pc) && getInlineReturnType() != MIRType_Boolean)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
if (getInlineArgType(argc, 0) != MIRType_Object)
|
if (getInlineThisType(callInfo) != MIRType_Object)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
if (getInlineArgType(argc, 1) != MIRType_String)
|
if (getInlineArgType(callInfo, 0) != MIRType_String)
|
||||||
return InliningStatus_NotInlined;
|
return InliningStatus_NotInlined;
|
||||||
|
|
||||||
MDefinitionVector argv;
|
callInfo.unwrapArgs();
|
||||||
if (!discardCall(argc, argv, current))
|
|
||||||
return InliningStatus_Error;
|
|
||||||
|
|
||||||
MInstruction *match = MRegExpTest::New(argv[0], argv[1]);
|
MInstruction *match = MRegExpTest::New(callInfo.thisArg(), callInfo.getArg(0));
|
||||||
current->add(match);
|
current->add(match);
|
||||||
current->push(match);
|
current->push(match);
|
||||||
if (!resumeAfter(match))
|
if (!resumeAfter(match))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче