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:
parent
b353b1d131
commit
d1b5a2518d
@ -1900,6 +1900,13 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
|
|||||||
if (instr->value()->type().IsSmi()) {
|
if (instr->value()->type().IsSmi()) {
|
||||||
value = UseRegisterAtStart(instr->value());
|
value = UseRegisterAtStart(instr->value());
|
||||||
res = DefineAsRegister(new(zone()) LSmiUntag(value, false));
|
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 {
|
} else {
|
||||||
value = UseRegister(instr->value());
|
value = UseRegister(instr->value());
|
||||||
LOperand* temp1 = TempRegister();
|
LOperand* temp1 = TempRegister();
|
||||||
|
@ -2087,6 +2087,7 @@ class LSmiUntag: public LTemplateInstruction<1, 1, 0> {
|
|||||||
LOperand* value() { return inputs_[0]; }
|
LOperand* value() { return inputs_[0]; }
|
||||||
bool needs_check() const { return needs_check_; }
|
bool needs_check() const { return needs_check_; }
|
||||||
|
|
||||||
|
DECLARE_HYDROGEN_ACCESSOR(Change);
|
||||||
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
|
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -4905,6 +4905,21 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
|||||||
// If the input is a HeapObject, SmiUntag will set the carry flag.
|
// If the input is a HeapObject, SmiUntag will set the carry flag.
|
||||||
__ SmiUntag(result, input, SetCC);
|
__ SmiUntag(result, input, SetCC);
|
||||||
DeoptimizeIf(cs, instr->environment());
|
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 {
|
} else {
|
||||||
__ SmiUntag(result, input);
|
__ SmiUntag(result, input);
|
||||||
}
|
}
|
||||||
|
@ -5411,7 +5411,7 @@ class HLoadKeyed
|
|||||||
IsFastDoubleElementsKind(elements_kind));
|
IsFastDoubleElementsKind(elements_kind));
|
||||||
|
|
||||||
if (IsFastSmiOrObjectElementsKind(elements_kind)) {
|
if (IsFastSmiOrObjectElementsKind(elements_kind)) {
|
||||||
if (elements_kind == FAST_SMI_ELEMENTS) {
|
if (IsFastSmiElementsKind(elements_kind)) {
|
||||||
set_type(HType::Smi());
|
set_type(HType::Smi());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5026,14 +5026,30 @@ void LCodeGen::DoSmiTag(LSmiTag* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
||||||
LOperand* input = instr->value();
|
LOperand* input = instr->value();
|
||||||
|
Register result = ToRegister(input);
|
||||||
ASSERT(input->IsRegister() && input->Equals(instr->result()));
|
ASSERT(input->IsRegister() && input->Equals(instr->result()));
|
||||||
if (instr->needs_check()) {
|
if (instr->needs_check()) {
|
||||||
__ test(ToRegister(input), Immediate(kSmiTagMask));
|
__ test(result, Immediate(kSmiTagMask));
|
||||||
DeoptimizeIf(not_zero, instr->environment());
|
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 {
|
} else {
|
||||||
__ AssertSmi(ToRegister(input));
|
__ AssertSmi(result);
|
||||||
}
|
}
|
||||||
__ SmiUntag(ToRegister(input));
|
__ SmiUntag(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1929,7 +1929,16 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
|
|||||||
ASSERT(to.IsInteger32());
|
ASSERT(to.IsInteger32());
|
||||||
if (instr->value()->type().IsSmi()) {
|
if (instr->value()->type().IsSmi()) {
|
||||||
LOperand* value = UseRegister(instr->value());
|
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 {
|
} else {
|
||||||
bool truncating = instr->CanTruncateToInt32();
|
bool truncating = instr->CanTruncateToInt32();
|
||||||
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
|
if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
|
||||||
|
@ -2153,6 +2153,7 @@ class LSmiUntag: public LTemplateInstruction<1, 1, 0> {
|
|||||||
LOperand* value() { return inputs_[0]; }
|
LOperand* value() { return inputs_[0]; }
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
|
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
|
||||||
|
DECLARE_HYDROGEN_ACCESSOR(Change);
|
||||||
|
|
||||||
bool needs_check() const { return needs_check_; }
|
bool needs_check() const { return needs_check_; }
|
||||||
|
|
||||||
|
@ -4606,6 +4606,21 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
|
|||||||
if (instr->needs_check()) {
|
if (instr->needs_check()) {
|
||||||
Condition is_smi = __ CheckSmi(input);
|
Condition is_smi = __ CheckSmi(input);
|
||||||
DeoptimizeIf(NegateCondition(is_smi), instr->environment());
|
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 {
|
} else {
|
||||||
__ AssertSmi(input);
|
__ AssertSmi(input);
|
||||||
}
|
}
|
||||||
|
@ -1825,7 +1825,16 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) {
|
|||||||
ASSERT(to.IsInteger32());
|
ASSERT(to.IsInteger32());
|
||||||
LOperand* value = UseRegister(instr->value());
|
LOperand* value = UseRegister(instr->value());
|
||||||
if (instr->value()->type().IsSmi()) {
|
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 {
|
} else {
|
||||||
bool truncating = instr->CanTruncateToInt32();
|
bool truncating = instr->CanTruncateToInt32();
|
||||||
LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
|
LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1);
|
||||||
|
@ -2011,6 +2011,7 @@ class LSmiUntag: public LTemplateInstruction<1, 1, 0> {
|
|||||||
LOperand* value() { return inputs_[0]; }
|
LOperand* value() { return inputs_[0]; }
|
||||||
bool needs_check() const { return needs_check_; }
|
bool needs_check() const { return needs_check_; }
|
||||||
|
|
||||||
|
DECLARE_HYDROGEN_ACCESSOR(Change);
|
||||||
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
|
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user