From 0e26f42bc1ffdad2287ea545a3521afa6e3a2122 Mon Sep 17 00:00:00 2001 From: "karlklose@chromium.org" Date: Fri, 14 Jan 2011 11:48:43 +0000 Subject: [PATCH] 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 --- src/arm/lithium-arm.cc | 17 ++++++------ src/arm/lithium-codegen-arm.cc | 61 +++++++++++++++++++++++++++++++++++++++--- src/arm/lithium-codegen-arm.h | 2 +- 3 files changed, 66 insertions(+), 14 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index a7dd71b..70b4812 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -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); diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 5d4745c..64471a9 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -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, diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h index 4ef772e..91e2e3f 100644 --- a/src/arm/lithium-codegen-arm.h +++ b/src/arm/lithium-codegen-arm.h @@ -71,7 +71,7 @@ class LCodeGen BASE_EMBEDDED { void FinishCode(Handle 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); -- 2.7.4