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
This commit is contained in:
verwaest@chromium.org 2013-05-22 16:32:33 +00:00
parent b353b1d131
commit d1b5a2518d
10 changed files with 80 additions and 6 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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_; }

View File

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

View File

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

View File

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