From: palfia@homejinni.com Date: Fri, 24 May 2013 01:02:27 +0000 (+0000) Subject: MIPS: Implement HChange support for Smis and use it in Load/StoreNameField X-Git-Tag: upstream/4.7.83~14145 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ae74636c9e8bceae7ab942e3019f1c9080e2263c;p=platform%2Fupstream%2Fv8.git MIPS: Implement HChange support for Smis and use it in Load/StoreNameField Port r14765 (22625125) BUG= Review URL: https://codereview.chromium.org/15781006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14782 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 49743fd..f7cb241 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -500,7 +500,7 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, Handle LCodeGen::ToHandle(LConstantOperand* op) const { HConstant* constant = chunk_->LookupConstant(op); - ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged()); + ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); return constant->handle(); } @@ -510,6 +510,11 @@ bool LCodeGen::IsInteger32(LConstantOperand* op) const { } +bool LCodeGen::IsSmi(LConstantOperand* op) const { + return chunk_->LookupLiteralRepresentation(op).IsSmi(); +} + + int LCodeGen::ToInteger32(LConstantOperand* op) const { HConstant* constant = chunk_->LookupConstant(op); return constant->Integer32Value(); @@ -1837,7 +1842,7 @@ void LCodeGen::DoBranch(LBranch* instr) { int false_block = chunk_->LookupDestination(instr->false_block_id()); Representation r = instr->hydrogen()->value()->representation(); - if (r.IsInteger32()) { + if (r.IsInteger32() || r.IsSmi()) { Register reg = ToRegister(instr->value()); EmitBranch(true_block, false_block, ne, reg, Operand(zero_reg)); } else if (r.IsDouble()) { @@ -3898,13 +3903,7 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { Handle transition = instr->transition(); - if (FLAG_track_fields && representation.IsSmi()) { - Register value = ToRegister(instr->value()); - __ SmiTagCheckOverflow(value, value, scratch); - if (!instr->hydrogen()->value()->range()->IsInSmiRange()) { - DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); - } - } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { + if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { Register value = ToRegister(instr->value()); if (!instr->hydrogen()->value()->type().IsHeapObject()) { __ And(scratch, value, Operand(kSmiTagMask)); @@ -4407,6 +4406,21 @@ void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { } +void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) { + LOperand* input = instr->value(); + ASSERT(input->IsRegister()); + LOperand* output = instr->result(); + ASSERT(output->IsRegister()); + Register scratch = scratch0(); + + __ SmiTagCheckOverflow(ToRegister(output), ToRegister(input), scratch); + if (!instr->hydrogen()->value()->HasRange() || + !instr->hydrogen()->value()->range()->IsInSmiRange()) { + DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); + } +} + + void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { LOperand* input = instr->value(); LOperand* output = instr->result(); @@ -4866,7 +4880,59 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { // Deopt if the operation did not succeed (except_flag != 0). DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); + + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { + Label done; + __ Branch(&done, ne, result_reg, Operand(zero_reg)); + __ mfc1(scratch1, double_input.high()); + __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); + DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); + __ bind(&done); + } + } +} + + +void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { + Register result_reg = ToRegister(instr->result()); + Register scratch1 = scratch0(); + Register scratch2 = ToRegister(instr->temp()); + DoubleRegister double_input = ToDoubleRegister(instr->value()); + + if (instr->truncating()) { + Register scratch3 = ToRegister(instr->temp2()); + FPURegister single_scratch = double_scratch0().low(); + __ EmitECMATruncate(result_reg, + double_input, + single_scratch, + scratch1, + scratch2, + scratch3); + } else { + Register except_flag = scratch2; + + __ EmitFPUTruncate(kRoundToMinusInf, + result_reg, + double_input, + scratch1, + double_scratch0(), + except_flag, + kCheckForInexactConversion); + + // Deopt if the operation did not succeed (except_flag != 0). + DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); + + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { + Label done; + __ Branch(&done, ne, result_reg, Operand(zero_reg)); + __ mfc1(scratch1, double_input.high()); + __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); + DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); + __ bind(&done); + } } + __ SmiTagCheckOverflow(result_reg, result_reg, scratch1); + DeoptimizeIf(lt, instr->environment(), scratch1, Operand(zero_reg)); } diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h index 90e7bf6..deefd06 100644 --- a/src/mips/lithium-codegen-mips.h +++ b/src/mips/lithium-codegen-mips.h @@ -125,6 +125,7 @@ class LCodeGen BASE_EMBEDDED { MemOperand ToHighMemOperand(LOperand* op) const; bool IsInteger32(LConstantOperand* op) const; + bool IsSmi(LConstantOperand* op) const; Handle ToHandle(LConstantOperand* op) const; // Try to generate code for the entire chunk, but it may fail if the diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 04125d1..758112c 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -1760,12 +1760,24 @@ LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { LInstruction* LChunkBuilder::DoChange(HChange* instr) { Representation from = instr->from(); Representation to = instr->to(); + if (from.IsSmi()) { + if (to.IsTagged()) { + LOperand* value = UseRegister(instr->value()); + return DefineSameAsFirst(new(zone()) LDummyUse(value)); + } + from = Representation::Tagged(); + } if (from.IsTagged()) { if (to.IsDouble()) { info()->MarkAsDeferredCalling(); LOperand* value = UseRegister(instr->value()); LNumberUntagD* res = new(zone()) LNumberUntagD(value); return AssignEnvironment(DefineAsRegister(res)); + } else if (to.IsSmi()) { + HValue* val = instr->value(); + LOperand* value = UseRegisterAtStart(val); + return AssignEnvironment( + DefineSameAsFirst(new(zone()) LCheckSmi(value))); } else { ASSERT(to.IsInteger32()); LOperand* value = NULL; @@ -1807,6 +1819,10 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2); Define(result, result_temp); return AssignPointerMap(result); + } else if (to.IsSmi()) { + LOperand* value = UseRegister(instr->value()); + return AssignEnvironment(DefineAsRegister(new(zone()) LDoubleToSmi(value, + TempRegister(), TempRegister()))); } else { ASSERT(to.IsInteger32()); LOperand* value = UseRegister(instr->value()); @@ -1829,6 +1845,15 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { LNumberTagI* result = new(zone()) LNumberTagI(value); return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); } + } else if (to.IsSmi()) { + HValue* val = instr->value(); + LOperand* value = UseRegister(val); + LInstruction* result = + DefineSameAsFirst(new(zone()) LInteger32ToSmi(value)); + if (val->HasRange() && val->range()->IsInSmiRange()) { + return result; + } + return AssignEnvironment(result); } else { ASSERT(to.IsDouble()); if (instr->value()->CheckFlag(HInstruction::kUint32)) { @@ -1923,7 +1948,7 @@ LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { return DefineAsRegister(new(zone()) LConstantI); } else if (r.IsDouble()) { return DefineAsRegister(new(zone()) LConstantD); - } else if (r.IsTagged()) { + } else if (r.IsTagged() || r.IsSmi()) { return DefineAsRegister(new(zone()) LConstantT); } else { UNREACHABLE(); diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h index 197254f..9606551 100644 --- a/src/mips/lithium-mips.h +++ b/src/mips/lithium-mips.h @@ -95,6 +95,7 @@ class LCodeGen; V(Deoptimize) \ V(DivI) \ V(DoubleToI) \ + V(DoubleToSmi) \ V(DummyUse) \ V(ElementsKind) \ V(FixedArrayBaseLength) \ @@ -111,6 +112,7 @@ class LCodeGen; V(InstanceSize) \ V(InstructionGap) \ V(Integer32ToDouble) \ + V(Integer32ToSmi) \ V(Uint32ToDouble) \ V(InvokeFunction) \ V(IsConstructCallAndBranch) \ @@ -1901,6 +1903,19 @@ class LInteger32ToDouble: public LTemplateInstruction<1, 1, 0> { }; +class LInteger32ToSmi: public LTemplateInstruction<1, 1, 0> { + public: + explicit LInteger32ToSmi(LOperand* value) { + inputs_[0] = value; + } + + LOperand* value() { return inputs_[0]; } + + DECLARE_CONCRETE_INSTRUCTION(Integer32ToSmi, "int32-to-smi") + DECLARE_HYDROGEN_ACCESSOR(Change) +}; + + class LUint32ToDouble: public LTemplateInstruction<1, 1, 0> { public: explicit LUint32ToDouble(LOperand* value) { @@ -1954,6 +1969,25 @@ class LNumberTagD: public LTemplateInstruction<1, 1, 2> { }; +class LDoubleToSmi: public LTemplateInstruction<1, 1, 2> { + public: + LDoubleToSmi(LOperand* value, LOperand* temp, LOperand* temp2) { + inputs_[0] = value; + temps_[0] = temp; + temps_[1] = temp2; + } + + LOperand* value() { return inputs_[0]; } + LOperand* temp() { return temps_[0]; } + LOperand* temp2() { return temps_[1]; } + + DECLARE_CONCRETE_INSTRUCTION(DoubleToSmi, "double-to-smi") + DECLARE_HYDROGEN_ACCESSOR(UnaryOperation) + + bool truncating() { return hydrogen()->CanTruncateToInt32(); } +}; + + // Sometimes truncating conversion from a tagged value to an int32. class LDoubleToI: public LTemplateInstruction<1, 1, 2> { public: @@ -2294,7 +2328,7 @@ class LCheckPrototypeMaps: public LTemplateInstruction<0, 0, 2> { }; -class LCheckSmi: public LTemplateInstruction<0, 1, 0> { +class LCheckSmi: public LTemplateInstruction<1, 1, 0> { public: explicit LCheckSmi(LOperand* value) { inputs_[0] = value;