Bug 877893 - Part 4: Make MToString support doubles and threadsafe. (r=djvj)

This commit is contained in:
Shu-yu Guo 2013-06-27 14:47:44 -07:00
parent 4bb320ae38
commit 8801ddfe23
10 changed files with 134 additions and 13 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -117,6 +117,7 @@
_(DoubleToInt32) \
_(TruncateDToInt32) \
_(IntToString) \
_(DoubleToString) \
_(Start) \
_(OsrEntry) \
_(OsrValue) \

View File

@ -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));

View File

@ -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). */ \

View File

@ -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.

View File

@ -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)

View File

@ -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)