mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 10:45:42 +00:00
Bug 877893 - Part 4: Make MToString support doubles and threadsafe. (r=djvj)
This commit is contained in:
parent
4bb320ae38
commit
8801ddfe23
@ -570,18 +570,33 @@ CodeGenerator::visitPolyInlineDispatch(LPolyInlineDispatch *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSFlatString *(*IntToStringFn)(JSContext *, int);
|
||||
typedef JSFlatString *(*IntToStringFn)(ThreadSafeContext *, int);
|
||||
static const VMFunction IntToStringInfo =
|
||||
FunctionInfo<IntToStringFn>(Int32ToString<CanGC>);
|
||||
|
||||
typedef ParallelResult (*ParallelIntToStringFn)(ForkJoinSlice *, int, MutableHandleString);
|
||||
static const VMFunction ParallelIntToStringInfo =
|
||||
FunctionInfo<ParallelIntToStringFn>(ParIntToString);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitIntToString(LIntToString *lir)
|
||||
{
|
||||
Register input = ToRegister(lir->input());
|
||||
Register output = ToRegister(lir->output());
|
||||
|
||||
OutOfLineCode *ool = oolCallVM(IntToStringInfo, lir, (ArgList(), input),
|
||||
StoreRegisterTo(output));
|
||||
OutOfLineCode *ool;
|
||||
switch (gen->info().executionMode()) {
|
||||
case SequentialExecution:
|
||||
ool = oolCallVM(IntToStringInfo, lir, (ArgList(), input),
|
||||
StoreRegisterTo(output));
|
||||
break;
|
||||
case ParallelExecution:
|
||||
ool = oolCallVM(ParallelIntToStringInfo, lir, (ArgList(), input),
|
||||
StoreRegisterTo(output));
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
}
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
@ -595,6 +610,48 @@ CodeGenerator::visitIntToString(LIntToString *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSString *(*DoubleToStringFn)(ThreadSafeContext *, double);
|
||||
static const VMFunction DoubleToStringInfo =
|
||||
FunctionInfo<DoubleToStringFn>(js_NumberToString<CanGC>);
|
||||
|
||||
typedef ParallelResult (*ParallelDoubleToStringFn)(ForkJoinSlice *, double, MutableHandleString);
|
||||
static const VMFunction ParallelDoubleToStringInfo =
|
||||
FunctionInfo<ParallelDoubleToStringFn>(ParDoubleToString);
|
||||
|
||||
bool
|
||||
CodeGenerator::visitDoubleToString(LDoubleToString *lir)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(lir->input());
|
||||
Register temp = ToRegister(lir->tempInt());
|
||||
Register output = ToRegister(lir->output());
|
||||
|
||||
OutOfLineCode *ool;
|
||||
switch (gen->info().executionMode()) {
|
||||
case SequentialExecution:
|
||||
ool = oolCallVM(DoubleToStringInfo, lir, (ArgList(), input),
|
||||
StoreRegisterTo(output));
|
||||
break;
|
||||
case ParallelExecution:
|
||||
ool = oolCallVM(ParallelDoubleToStringInfo, lir, (ArgList(), input),
|
||||
StoreRegisterTo(output));
|
||||
break;
|
||||
default:
|
||||
JS_NOT_REACHED("No such execution mode");
|
||||
}
|
||||
if (!ool)
|
||||
return false;
|
||||
|
||||
masm.convertDoubleToInt32(input, temp, ool->entry(), true);
|
||||
masm.branch32(Assembler::AboveOrEqual, temp, Imm32(StaticStrings::INT_STATIC_LIMIT),
|
||||
ool->entry());
|
||||
|
||||
masm.movePtr(ImmWord(&gen->compartment->rt->staticStrings.intStaticTable), output);
|
||||
masm.loadPtr(BaseIndex(output, temp, ScalePointer), output);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject *(*CloneRegExpObjectFn)(JSContext *, JSObject *, JSObject *);
|
||||
static const VMFunction CloneRegExpObjectInfo =
|
||||
FunctionInfo<CloneRegExpObjectFn>(CloneRegExpObject);
|
||||
|
@ -75,6 +75,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitTypeObjectDispatch(LTypeObjectDispatch *lir);
|
||||
bool visitPolyInlineDispatch(LPolyInlineDispatch *lir);
|
||||
bool visitIntToString(LIntToString *lir);
|
||||
bool visitDoubleToString(LDoubleToString *lir);
|
||||
bool visitInteger(LInteger *lir);
|
||||
bool visitRegExp(LRegExp *lir);
|
||||
bool visitRegExpTest(LRegExpTest *lir);
|
||||
|
@ -3290,9 +3290,14 @@ IonBuilder::jsop_binary(JSOp op, MDefinition *left, MDefinition *right)
|
||||
// Do a string concatenation if adding two inputs that are int or string
|
||||
// and at least one is a string.
|
||||
if (op == JSOP_ADD &&
|
||||
(left->type() == MIRType_String || right->type() == MIRType_String) &&
|
||||
(left->type() == MIRType_String || left->type() == MIRType_Int32) &&
|
||||
(right->type() == MIRType_String || right->type() == MIRType_Int32))
|
||||
((left->type() == MIRType_String &&
|
||||
(right->type() == MIRType_String ||
|
||||
right->type() == MIRType_Int32 ||
|
||||
right->type() == MIRType_Double)) ||
|
||||
(left->type() == MIRType_Int32 &&
|
||||
right->type() == MIRType_String) ||
|
||||
(left->type() == MIRType_Double &&
|
||||
right->type() == MIRType_String)))
|
||||
{
|
||||
MConcat *ins = MConcat::New(left, right);
|
||||
current->add(ins);
|
||||
|
@ -2477,8 +2477,7 @@ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1>
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a any input type hosted on one definition to a string with a function
|
||||
// call.
|
||||
// Convert an integer hosted on one definition to a string with a function call.
|
||||
class LIntToString : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
@ -2493,6 +2492,25 @@ class LIntToString : public LInstructionHelper<1, 1, 0>
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a double hosted on one definition to a string with a function call.
|
||||
class LDoubleToString : public LInstructionHelper<1, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(DoubleToString)
|
||||
|
||||
LDoubleToString(const LAllocation &input, const LDefinition &temp) {
|
||||
setOperand(0, input);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LDefinition *tempInt() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const MToString *mir() {
|
||||
return mir_->toToString();
|
||||
}
|
||||
};
|
||||
|
||||
// No-op instruction that is used to hold the entry snapshot. This simplifies
|
||||
// register allocation as it doesn't need to sniff the snapshot out of the
|
||||
// LIRGraph.
|
||||
|
@ -117,6 +117,7 @@
|
||||
_(DoubleToInt32) \
|
||||
_(TruncateDToInt32) \
|
||||
_(IntToString) \
|
||||
_(DoubleToString) \
|
||||
_(Start) \
|
||||
_(OsrEntry) \
|
||||
_(OsrValue) \
|
||||
|
@ -1543,13 +1543,20 @@ LIRGenerator::visitToString(MToString *ins)
|
||||
MDefinition *opd = ins->input();
|
||||
|
||||
switch (opd->type()) {
|
||||
case MIRType_Double:
|
||||
case MIRType_Null:
|
||||
case MIRType_Undefined:
|
||||
case MIRType_Boolean:
|
||||
JS_NOT_REACHED("NYI: Lower MToString");
|
||||
return false;
|
||||
|
||||
case MIRType_Double: {
|
||||
LDoubleToString *lir = new LDoubleToString(useRegister(opd), temp());
|
||||
|
||||
if (!define(lir, ins))
|
||||
return false;
|
||||
return assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
case MIRType_Int32: {
|
||||
LIntToString *lir = new LIntToString(useRegister(opd));
|
||||
|
||||
|
@ -205,6 +205,26 @@ ion::ParConcatStrings(ForkJoinSlice *slice, HandleString left, HandleString righ
|
||||
return TP_SUCCESS;
|
||||
}
|
||||
|
||||
ParallelResult
|
||||
ion::ParIntToString(ForkJoinSlice *slice, int i, MutableHandleString out)
|
||||
{
|
||||
JSFlatString *str = Int32ToString<NoGC>(slice, i);
|
||||
if (!str)
|
||||
return TP_RETRY_SEQUENTIALLY;
|
||||
out.set(str);
|
||||
return TP_SUCCESS;
|
||||
}
|
||||
|
||||
ParallelResult
|
||||
ion::ParDoubleToString(ForkJoinSlice *slice, double d, MutableHandleString out)
|
||||
{
|
||||
JSString *str = js_NumberToString<NoGC>(slice, d);
|
||||
if (!str)
|
||||
return TP_RETRY_SEQUENTIALLY;
|
||||
out.set(str);
|
||||
return TP_SUCCESS;
|
||||
}
|
||||
|
||||
#define PAR_RELATIONAL_OP(OP, EXPECTED) \
|
||||
do { \
|
||||
/* Optimize for two int-tagged operands (typical loop control). */ \
|
||||
|
@ -41,9 +41,12 @@ JSObject* ParPush(ParPushArgs *args);
|
||||
// generation.
|
||||
JSObject *ParExtendArray(ForkJoinSlice *slice, JSObject *array, uint32_t length);
|
||||
|
||||
// Concatenate two strings.
|
||||
// String related parallel functions. These tend to call existing VM functions
|
||||
// that take a ThreadSafeContext.
|
||||
ParallelResult ParConcatStrings(ForkJoinSlice *slice, HandleString left, HandleString right,
|
||||
MutableHandleString out);
|
||||
ParallelResult ParIntToString(ForkJoinSlice *slice, int i, MutableHandleString out);
|
||||
ParallelResult ParDoubleToString(ForkJoinSlice *slice, double d, MutableHandleString out);
|
||||
|
||||
// These parallel operations fail if they would be required to convert
|
||||
// to a string etc etc.
|
||||
|
@ -168,7 +168,7 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
||||
SAFE_OP(ToDouble)
|
||||
SAFE_OP(ToInt32)
|
||||
SAFE_OP(TruncateToInt32)
|
||||
UNSAFE_OP(ToString)
|
||||
CUSTOM_OP(ToString)
|
||||
SAFE_OP(NewSlots)
|
||||
CUSTOM_OP(NewArray)
|
||||
CUSTOM_OP(NewObject)
|
||||
@ -562,6 +562,15 @@ ParallelSafetyVisitor::visitConcat(MConcat *ins)
|
||||
return replace(ins, MParConcat::New(parSlice(), ins));
|
||||
}
|
||||
|
||||
bool
|
||||
ParallelSafetyVisitor::visitToString(MToString *ins)
|
||||
{
|
||||
MIRType inputType = ins->input()->type();
|
||||
if (inputType != MIRType_Int32 && inputType != MIRType_Double)
|
||||
return markUnsafe();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ParallelSafetyVisitor::replaceWithParNew(MInstruction *newInstruction,
|
||||
JSObject *templateObject)
|
||||
|
@ -77,7 +77,7 @@ BinaryStringPolicy::adjustInputs(MInstruction *ins)
|
||||
continue;
|
||||
|
||||
MInstruction *replace = NULL;
|
||||
if (in->type() == MIRType_Int32) {
|
||||
if (in->type() == MIRType_Int32 || in->type() == MIRType_Double) {
|
||||
replace = MToString::New(in);
|
||||
} else {
|
||||
if (in->type() != MIRType_Value)
|
||||
@ -300,7 +300,7 @@ StringPolicy<Op>::staticAdjustInputs(MInstruction *def)
|
||||
return true;
|
||||
|
||||
MInstruction *replace;
|
||||
if (in->type() == MIRType_Int32) {
|
||||
if (in->type() == MIRType_Int32 || in->type() == MIRType_Double) {
|
||||
replace = MToString::New(in);
|
||||
} else {
|
||||
if (in->type() != MIRType_Value)
|
||||
|
Loading…
Reference in New Issue
Block a user