ARM: Implement DoModI stub in the lithium code generator.

BUG=
TEST=

Review URL: http://codereview.chromium.org/6314003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6312 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
karlklose@chromium.org 2011-01-14 11:48:43 +00:00
parent 7954752479
commit 0e26f42bc1
3 changed files with 66 additions and 14 deletions

View File

@ -1255,18 +1255,17 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
LInstruction* LChunkBuilder::DoMod(HMod* instr) {
if (instr->representation().IsInteger32()) {
// TODO(1042) The fixed register allocation
// is needed because we call GenericBinaryOpStub from
// the generated code, which requires registers r0
// and r1 to be used. We should remove that
// when we provide a native implementation.
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
// The temporary operand is necessary to ensure that right is not allocated
// into edx.
FixedTemp(r1);
LOperand* value = UseFixed(instr->left(), r0);
LOperand* divisor = UseRegister(instr->right());
LInstruction* result = DefineFixed(new LModI(value, divisor), r1);
if (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
instr->CheckFlag(HValue::kCanBeDivByZero)) {
result = AssignEnvironment(result);
}
LOperand* divisor = UseFixed(instr->right(), r1);
LInstruction* result = DefineFixed(new LModI(value, divisor), r0);
result = AssignEnvironment(AssignPointerMap(result));
return result;
} else if (instr->representation().IsTagged()) {
return DoArithmeticT(Token::MOD, instr);

View File

@ -848,7 +848,57 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
void LCodeGen::DoModI(LModI* instr) {
Abort("DoModI unimplemented.");
class DeferredModI: public LDeferredCode {
public:
DeferredModI(LCodeGen* codegen, LModI* instr)
: LDeferredCode(codegen), instr_(instr) { }
virtual void Generate() {
codegen()->DoDeferredGenericBinaryStub(instr_, Token::MOD);
}
private:
LModI* instr_;
};
// These registers hold untagged 32 bit values.
Register left = ToRegister(instr->left());
Register right = ToRegister(instr->right());
Register result = ToRegister(instr->result());
Register scratch = scratch0();
Label deoptimize, done;
// Check for x % 0.
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
__ tst(right, Operand(right));
__ b(eq, &deoptimize);
}
// Check for (0 % -x) that will produce negative zero.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label ok;
__ tst(left, Operand(left));
__ b(ne, &ok);
__ tst(right, Operand(right));
__ b(pl, &ok);
__ b(al, &deoptimize);
__ bind(&ok);
}
// Call the generic stub. The numbers in r0 and r1 have
// to be tagged to Smis. If that is not possible, deoptimize.
DeferredModI* deferred = new DeferredModI(this, instr);
__ TrySmiTag(left, &deoptimize, scratch);
__ TrySmiTag(right, &deoptimize, scratch);
__ b(al, deferred->entry());
__ bind(deferred->exit());
// If the result in r0 is a Smi, untag it, else deoptimize.
__ BranchOnNotSmi(result, &deoptimize);
__ mov(result, Operand(result, ASR, 1));
__ b(al, &done);
__ bind(&deoptimize);
DeoptimizeIf(al, instr->environment());
__ bind(&done);
}
@ -857,7 +907,9 @@ void LCodeGen::DoDivI(LDivI* instr) {
public:
DeferredDivI(LCodeGen* codegen, LDivI* instr)
: LDeferredCode(codegen), instr_(instr) { }
virtual void Generate() { codegen()->DoDeferredDivI(instr_); }
virtual void Generate() {
codegen()->DoDeferredGenericBinaryStub(instr_, Token::DIV);
}
private:
LDivI* instr_;
};
@ -930,12 +982,13 @@ void LCodeGen::DoDivI(LDivI* instr) {
}
void LCodeGen::DoDeferredDivI(LDivI* instr) {
void LCodeGen::DoDeferredGenericBinaryStub(LBinaryOperation* instr,
Token::Value op) {
Register left = ToRegister(instr->left());
Register right = ToRegister(instr->right());
__ PushSafepointRegistersAndDoubles();
GenericBinaryOpStub stub(Token::DIV, OVERWRITE_LEFT, left, right);
GenericBinaryOpStub stub(op, OVERWRITE_LEFT, left, right);
__ CallStub(&stub);
RecordSafepointWithRegisters(instr->pointer_map(),
0,

View File

@ -71,7 +71,7 @@ class LCodeGen BASE_EMBEDDED {
void FinishCode(Handle<Code> code);
// Deferred code support.
void DoDeferredDivI(LDivI* instr);
void DoDeferredGenericBinaryStub(LBinaryOperation* instr, Token::Value op);
void DoDeferredNumberTagD(LNumberTagD* instr);
void DoDeferredNumberTagI(LNumberTagI* instr);
void DoDeferredTaggedToI(LTaggedToI* instr);