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();
LOperand* value() { return inputs_[0]; }
bool needs_check() const { return needs_check_; }
+ DECLARE_HYDROGEN_ACCESSOR(Change);
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
private:
// 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);
}
IsFastDoubleElementsKind(elements_kind));
if (IsFastSmiOrObjectElementsKind(elements_kind)) {
- if (elements_kind == FAST_SMI_ELEMENTS) {
+ if (IsFastSmiElementsKind(elements_kind)) {
set_type(HType::Smi());
}
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);
}
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)) {
LOperand* value() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
+ DECLARE_HYDROGEN_ACCESSOR(Change);
bool needs_check() const { return needs_check_; }
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);
}
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);
LOperand* value() { return inputs_[0]; }
bool needs_check() const { return needs_check_; }
+ DECLARE_HYDROGEN_ACCESSOR(Change);
DECLARE_CONCRETE_INSTRUCTION(SmiUntag, "smi-untag")
private: