From d1b5a2518d86a8d0b6900e67d19fd53652d75c45 Mon Sep 17 00:00:00 2001 From: "verwaest@chromium.org" Date: Wed, 22 May 2013 16:32:33 +0000 Subject: [PATCH] Handle holes in smi-untag from LoadKeyed requiring hole handling. R=jkummerow@chromium.org Review URL: https://chromiumcodereview.appspot.com/15737003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14756 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 7 +++++++ src/arm/lithium-arm.h | 1 + src/arm/lithium-codegen-arm.cc | 15 +++++++++++++++ src/hydrogen-instructions.h | 2 +- src/ia32/lithium-codegen-ia32.cc | 22 +++++++++++++++++++--- src/ia32/lithium-ia32.cc | 11 ++++++++++- src/ia32/lithium-ia32.h | 1 + src/x64/lithium-codegen-x64.cc | 15 +++++++++++++++ src/x64/lithium-x64.cc | 11 ++++++++++- src/x64/lithium-x64.h | 1 + 10 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index e1bb69e..54efacb 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1900,6 +1900,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { if (instr->value()->type().IsSmi()) { value = UseRegisterAtStart(instr->value()); res = DefineAsRegister(new(zone()) LSmiUntag(value, false)); + if (instr->value()->IsLoadKeyed()) { + HLoadKeyed* load_keyed = HLoadKeyed::cast(instr->value()); + if (load_keyed->UsesMustHandleHole() && + load_keyed->hole_mode() == NEVER_RETURN_HOLE) { + res = AssignEnvironment(res); + } + } } else { value = UseRegister(instr->value()); LOperand* temp1 = TempRegister(); diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 9bcd44a..c9d61b9 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -2087,6 +2087,7 @@ class LSmiUntag: public LTemplateInstruction<1, 1, 0> { LOperand* value() { return inputs_[0]; } bool needs_check() const { return needs_check_; } + DECLARE_HYDROGEN_ACCESSOR(Change); DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag") private: diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 09a0e9c..e12fcb7 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -4905,6 +4905,21 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { // If the input is a HeapObject, SmiUntag will set the carry flag. __ SmiUntag(result, input, SetCC); DeoptimizeIf(cs, instr->environment()); + } else if (instr->hydrogen()->value()->IsLoadKeyed()) { + HLoadKeyed* load = HLoadKeyed::cast(instr->hydrogen()->value()); + if (load->UsesMustHandleHole()) { + __ SmiUntag(result, input, SetCC); + if (load->hole_mode() == ALLOW_RETURN_HOLE) { + Label done; + __ b(cc, &done); + __ mov(result, Operand(Smi::FromInt(0))); + __ bind(&done); + } else { + DeoptimizeIf(cs, instr->environment()); + } + } else { + __ SmiUntag(result, input); + } } else { __ SmiUntag(result, input); } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index c6a5111..f16efe6 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -5411,7 +5411,7 @@ class HLoadKeyed IsFastDoubleElementsKind(elements_kind)); if (IsFastSmiOrObjectElementsKind(elements_kind)) { - if (elements_kind == FAST_SMI_ELEMENTS) { + if (IsFastSmiElementsKind(elements_kind)) { set_type(HType::Smi()); } diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index b6244af..bf014da 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -5026,14 +5026,30 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) { void LCodeGen::DoSmiUntag(LSmiUntag* instr) { LOperand* input = instr->value(); + Register result = ToRegister(input); ASSERT(input->IsRegister() && input->Equals(instr->result())); if (instr->needs_check()) { - __ test(ToRegister(input), Immediate(kSmiTagMask)); + __ test(result, Immediate(kSmiTagMask)); DeoptimizeIf(not_zero, instr->environment()); + } else if (instr->hydrogen()->value()->IsLoadKeyed()) { + HLoadKeyed* load = HLoadKeyed::cast(instr->hydrogen()->value()); + if (load->UsesMustHandleHole()) { + __ test(result, Immediate(kSmiTagMask)); + if (load->hole_mode() == ALLOW_RETURN_HOLE) { + Label done; + __ j(equal, &done); + __ xor_(result, result); + __ bind(&done); + } else { + DeoptimizeIf(not_zero, instr->environment()); + } + } else { + __ AssertSmi(result); + } } else { - __ AssertSmi(ToRegister(input)); + __ AssertSmi(result); } - __ SmiUntag(ToRegister(input)); + __ SmiUntag(result); } diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index dec5697..8179753 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -1929,7 +1929,16 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ASSERT(to.IsInteger32()); if (instr->value()->type().IsSmi()) { LOperand* value = UseRegister(instr->value()); - return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); + LInstruction* result = + DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); + if (instr->value()->IsLoadKeyed()) { + HLoadKeyed* load_keyed = HLoadKeyed::cast(instr->value()); + if (load_keyed->UsesMustHandleHole() && + load_keyed->hole_mode() == NEVER_RETURN_HOLE) { + return AssignEnvironment(result); + } + } + return result; } else { bool truncating = instr->CanTruncateToInt32(); if (CpuFeatures::IsSafeForSnapshot(SSE2)) { diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index b32ead9..a7d9fb4 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -2153,6 +2153,7 @@ class LSmiUntag: public LTemplateInstruction<1, 1, 0> { LOperand* value() { return inputs_[0]; } DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag") + DECLARE_HYDROGEN_ACCESSOR(Change); bool needs_check() const { return needs_check_; } diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 9a1ce98..42c6e91 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -4606,6 +4606,21 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { if (instr->needs_check()) { Condition is_smi = __ CheckSmi(input); DeoptimizeIf(NegateCondition(is_smi), instr->environment()); + } else if (instr->hydrogen()->value()->IsLoadKeyed()) { + HLoadKeyed* load = HLoadKeyed::cast(instr->hydrogen()->value()); + if (load->UsesMustHandleHole()) { + Condition cc = masm()->CheckSmi(input); + if (load->hole_mode() == ALLOW_RETURN_HOLE) { + Label done; + __ j(cc, &done); + __ xor_(input, input); + __ bind(&done); + } else { + DeoptimizeIf(NegateCondition(cc), instr->environment()); + } + } else { + __ AssertSmi(input); + } } else { __ AssertSmi(input); } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 1217a40..cde4e86 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1825,7 +1825,16 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { ASSERT(to.IsInteger32()); LOperand* value = UseRegister(instr->value()); if (instr->value()->type().IsSmi()) { - return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); + LInstruction* result = + DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); + if (instr->value()->IsLoadKeyed()) { + HLoadKeyed* load_keyed = HLoadKeyed::cast(instr->value()); + if (load_keyed->UsesMustHandleHole() && + load_keyed->hole_mode() == NEVER_RETURN_HOLE) { + return AssignEnvironment(result); + } + } + return result; } else { bool truncating = instr->CanTruncateToInt32(); LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1); diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index 747d8e7..9926fc3 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -2011,6 +2011,7 @@ class LSmiUntag: public LTemplateInstruction<1, 1, 0> { LOperand* value() { return inputs_[0]; } bool needs_check() const { return needs_check_; } + DECLARE_HYDROGEN_ACCESSOR(Change); DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag") private: -- 2.7.4