diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index c85238f195..700617aea9 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -2000,7 +2000,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { } -LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { +LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { LOperand* value = UseRegisterAtStart(instr->value()); return AssignEnvironment(new(zone()) LCheckNonSmi(value)); } diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index ec5e7314b2..f34b623e38 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -2421,6 +2421,7 @@ class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> { LOperand* value() { return inputs_[0]; } DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi") + DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject) }; diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index df2063ed75..0ad42db4f3 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -1880,10 +1880,12 @@ void LCodeGen::DoValueOf(LValueOf* instr) { Register map = ToRegister(instr->temp()); Label done; - // If the object is a smi return the object. - __ SmiTst(input); - __ Move(result, input, eq); - __ b(eq, &done); + if (!instr->hydrogen()->value()->IsHeapObject()) { + // If the object is a smi return the object. + __ SmiTst(input); + __ Move(result, input, eq); + __ b(eq, &done); + } // If the object is not a value type, return the object. __ CompareObjectType(input, map, map, JS_VALUE_TYPE); @@ -2438,8 +2440,11 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { Condition LCodeGen::EmitIsString(Register input, Register temp1, - Label* is_not_string) { - __ JumpIfSmi(input, is_not_string); + Label* is_not_string, + SmiCheck check_needed = INLINE_SMI_CHECK) { + if (check_needed == INLINE_SMI_CHECK) { + __ JumpIfSmi(input, is_not_string); + } __ CompareObjectType(input, temp1, temp1, FIRST_NONSTRING_TYPE); return lt; @@ -2450,8 +2455,11 @@ void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { Register reg = ToRegister(instr->value()); Register temp1 = ToRegister(instr->temp()); + SmiCheck check_needed = + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; Condition true_cond = - EmitIsString(reg, temp1, instr->FalseLabel(chunk_)); + EmitIsString(reg, temp1, instr->FalseLabel(chunk_), check_needed); EmitBranch(instr, true_cond); } @@ -2468,7 +2476,9 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { Register input = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + if (!instr->hydrogen()->value()->IsHeapObject()) { + __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + } __ ldr(temp, FieldMemOperand(input, HeapObject::kMapOffset)); __ ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); __ tst(temp, Operand(1 << Map::kIsUndetectable)); @@ -2534,7 +2544,9 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { Register scratch = scratch0(); Register input = ToRegister(instr->value()); - __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + if (!instr->hydrogen()->value()->IsHeapObject()) { + __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + } __ CompareObjectType(input, scratch, scratch, TestType(instr->hydrogen())); EmitBranch(instr, BranchCondition(instr->hydrogen())); @@ -2969,9 +2981,9 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { __ str(value, target); if (instr->hydrogen()->NeedsWriteBarrier()) { - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; __ RecordWriteContextSlot(context, target.offset(), value, @@ -4209,9 +4221,9 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { // Do the store. Register value = ToRegister(instr->value()); ASSERT(!object.is(value)); - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; if (access.IsInobject()) { __ str(value, FieldMemOperand(object, offset)); if (instr->hydrogen()->NeedsWriteBarrier()) { @@ -4420,9 +4432,9 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { __ str(value, FieldMemOperand(store_base, offset)); if (instr->hydrogen()->NeedsWriteBarrier()) { - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; // Compute address of modified element and store it into key register. __ add(key, store_base, Operand(offset - kHeapObjectTag)); __ RecordWrite(elements, @@ -5144,9 +5156,11 @@ void LCodeGen::DoCheckSmi(LCheckSmi* instr) { void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { - LOperand* input = instr->value(); - __ SmiTst(ToRegister(input)); - DeoptimizeIf(eq, instr->environment()); + if (!instr->hydrogen()->value()->IsHeapObject()) { + LOperand* input = instr->value(); + __ SmiTst(ToRegister(input)); + DeoptimizeIf(eq, instr->environment()); + } } diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h index 9202dd5a56..075fb416c7 100644 --- a/src/arm/lithium-codegen-arm.h +++ b/src/arm/lithium-codegen-arm.h @@ -349,7 +349,8 @@ class LCodeGen BASE_EMBEDDED { // true and false label should be made, to optimize fallthrough. Condition EmitIsString(Register input, Register temp1, - Label* is_not_string); + Label* is_not_string, + SmiCheck check_needed); // Emits optimized code for %_IsConstructCall(). // Caller should branch on equal condition. diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 1431727f81..cd4427090f 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -3065,9 +3065,8 @@ HType HCheckFunction::CalculateInferredType() { } -HType HCheckNonSmi::CalculateInferredType() { - // TODO(kasperl): Is there any way to signal that this isn't a smi? - return HType::Tagged(); +HType HCheckHeapObject::CalculateInferredType() { + return HType::NonPrimitive(); } @@ -3736,7 +3735,7 @@ void HSimulate::Verify() { } -void HCheckNonSmi::Verify() { +void HCheckHeapObject::Verify() { HInstruction::Verify(); ASSERT(HasNoUses()); } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 6de90deb5b..c765d62cd7 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -89,9 +89,9 @@ class LChunkBuilder; V(CallStub) \ V(Change) \ V(CheckFunction) \ + V(CheckHeapObject) \ V(CheckInstanceType) \ V(CheckMaps) \ - V(CheckNonSmi) \ V(CheckPrototypeMaps) \ V(ClampToUint8) \ V(ClassOfTestAndBranch) \ @@ -434,7 +434,7 @@ class HType { bool IsHeapObject() const { ASSERT(type_ != kUninitialized); - return IsHeapNumber() || IsString() || IsNonPrimitive(); + return IsHeapNumber() || IsString() || IsBoolean() || IsNonPrimitive(); } static HType TypeFromValue(Handle value); @@ -918,6 +918,10 @@ class HValue: public ZoneObject { type_ = new_type; } + bool IsHeapObject() { + return representation_.IsHeapObject() || type_.IsHeapObject(); + } + // An operation needs to override this function iff: // 1) it can produce an int32 output. // 2) the true value of its output can potentially be minus zero. @@ -2948,9 +2952,9 @@ class HCheckInstanceType: public HUnaryOperation { }; -class HCheckNonSmi: public HUnaryOperation { +class HCheckHeapObject: public HUnaryOperation { public: - explicit HCheckNonSmi(HValue* value) : HUnaryOperation(value) { + explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) { set_representation(Representation::Tagged()); SetFlag(kUseGVN); } @@ -2967,17 +2971,13 @@ class HCheckNonSmi: public HUnaryOperation { virtual HValue* Canonicalize() { HType value_type = value()->type(); - if (!value_type.IsUninitialized() && - (value_type.IsHeapNumber() || - value_type.IsString() || - value_type.IsBoolean() || - value_type.IsNonPrimitive())) { + if (!value_type.IsUninitialized() && value_type.IsHeapObject()) { return NULL; } return this; } - DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi) + DECLARE_CONCRETE_INSTRUCTION(CheckHeapObject) protected: virtual bool DataEquals(HValue* other) { return true; } diff --git a/src/hydrogen.cc b/src/hydrogen.cc index b03bf69938..e96b51cd74 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -1024,9 +1024,9 @@ HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { } -HValue* HGraphBuilder::BuildCheckNonSmi(HValue* obj) { +HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { if (obj->type().IsHeapObject()) return obj; - HCheckNonSmi* check = new(zone()) HCheckNonSmi(obj); + HCheckHeapObject* check = new(zone()) HCheckHeapObject(obj); AddInstruction(check); return check; } @@ -1703,7 +1703,7 @@ void HGraphBuilder::BuildCompareNil( if_nil.Then(); if_nil.Else(); if (type->NumClasses() == 1) { - BuildCheckNonSmi(value); + BuildCheckHeapObject(value); // For ICs, the map checked below is a sentinel map that gets replaced by // the monomorphic map when the code is used as a template to generate a // new IC. For optimized functions, there is no sentinel map, the map @@ -6158,14 +6158,14 @@ static Representation ComputeLoadStoreRepresentation(Handle type, void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle map) { - BuildCheckNonSmi(object); + BuildCheckHeapObject(object); AddInstruction(HCheckMaps::New(object, map, zone())); } void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, Handle map) { - BuildCheckNonSmi(object); + BuildCheckHeapObject(object); AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); } @@ -6334,7 +6334,7 @@ HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( if (count != types->length()) return NULL; // Everything matched; can use monomorphic load. - BuildCheckNonSmi(object); + BuildCheckHeapObject(object); AddInstruction(HCheckMaps::New(object, types, zone())); return BuildLoadNamedField(object, access, representation); } @@ -6349,7 +6349,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( expr, object, types, name); if (instr == NULL) { // Something did not match; must use a polymorphic load. - BuildCheckNonSmi(object); + BuildCheckHeapObject(object); HValue* context = environment()->LookupContext(); instr = new(zone()) HLoadNamedFieldPolymorphic( context, object, types, name, zone()); @@ -6405,7 +6405,7 @@ bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( if (count != types->length()) return false; // Everything matched; can use monomorphic store. - BuildCheckNonSmi(object); + BuildCheckHeapObject(object); AddInstruction(HCheckMaps::New(object, types, zone())); HInstruction* store; CHECK_ALIVE_OR_RETURN( @@ -6444,7 +6444,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( LookupResult lookup(isolate()); if (ComputeLoadStoreField(map, name, &lookup, true)) { if (count == 0) { - BuildCheckNonSmi(object); + BuildCheckHeapObject(object); join = graph()->CreateBasicBlock(); } ++count; @@ -7178,7 +7178,7 @@ HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( KeyedAccessStoreMode store_mode, bool* has_side_effects) { *has_side_effects = false; - BuildCheckNonSmi(object); + BuildCheckHeapObject(object); SmallMapList* maps = prop->GetReceiverTypes(); bool todo_external_array = false; @@ -7403,7 +7403,7 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( : BuildLoadKeyedGeneric(obj, key); AddInstruction(instr); } else { - BuildCheckNonSmi(obj); + BuildCheckHeapObject(obj); instr = BuildMonomorphicElementAccess( obj, key, val, NULL, map, is_store, expr->GetStoreMode()); } @@ -7535,7 +7535,7 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) { HInstruction* instr = NULL; if (expr->IsStringLength()) { HValue* string = Pop(); - BuildCheckNonSmi(string); + BuildCheckHeapObject(string); AddInstruction(HCheckInstanceType::NewIsString(string, zone())); instr = HStringLength::New(zone(), string); } else if (expr->IsStringAccess()) { @@ -7550,7 +7550,7 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) { } else if (expr->IsFunctionPrototype()) { HValue* function = Pop(); - BuildCheckNonSmi(function); + BuildCheckHeapObject(function); instr = new(zone()) HLoadFunctionPrototype(function); } else if (expr->key()->IsPropertyName()) { @@ -7724,7 +7724,7 @@ void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( empty_smi_block->Goto(number_block); set_current_block(not_smi_block); } else { - BuildCheckNonSmi(receiver); + BuildCheckHeapObject(receiver); } } HBasicBlock* if_true = graph()->CreateBasicBlock(); @@ -9335,7 +9335,7 @@ HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( return new(zone()) HConstant(s->Get(i)); } } - BuildCheckNonSmi(string); + BuildCheckHeapObject(string); AddInstruction(HCheckInstanceType::NewIsString(string, zone())); HInstruction* length = HStringLength::New(zone(), string); AddInstruction(length); @@ -9426,9 +9426,9 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( switch (expr->op()) { case Token::ADD: if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { - BuildCheckNonSmi(left); + BuildCheckHeapObject(left); AddInstruction(HCheckInstanceType::NewIsString(left, zone())); - BuildCheckNonSmi(right); + BuildCheckHeapObject(right); AddInstruction(HCheckInstanceType::NewIsString(right, zone())); instr = HStringAdd::New(zone(), context, left, right); } else { @@ -9845,9 +9845,9 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { result->set_position(expr->position()); return ast_context()->ReturnControl(result, expr->id()); } else { - BuildCheckNonSmi(left); + BuildCheckHeapObject(left); AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); - BuildCheckNonSmi(right); + BuildCheckHeapObject(right); AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); HCompareObjectEqAndBranch* result = new(zone()) HCompareObjectEqAndBranch(left, right); @@ -9860,9 +9860,9 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { } } else if (combined_type->Is(Type::InternalizedString()) && Token::IsEqualityOp(op)) { - BuildCheckNonSmi(left); + BuildCheckHeapObject(left); AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); - BuildCheckNonSmi(right); + BuildCheckHeapObject(right); AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); HCompareObjectEqAndBranch* result = new(zone()) HCompareObjectEqAndBranch(left, right); diff --git a/src/hydrogen.h b/src/hydrogen.h index fdd2f75779..f9aaf68ea2 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1012,7 +1012,7 @@ class HGraphBuilder { HBasicBlock* CreateBasicBlock(HEnvironment* env); HBasicBlock* CreateLoopHeaderBlock(); - HValue* BuildCheckNonSmi(HValue* object); + HValue* BuildCheckHeapObject(HValue* object); HValue* BuildCheckMap(HValue* obj, Handle map); // Building common constructs diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index eaab558ce6..18c95cc65b 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -1810,8 +1810,11 @@ void LCodeGen::DoValueOf(LValueOf* instr) { ASSERT(input.is(result)); Label done; - // If the object is a smi return the object. - __ JumpIfSmi(input, &done, Label::kNear); + + if (!instr->hydrogen()->value()->IsHeapObject()) { + // If the object is a smi return the object. + __ JumpIfSmi(input, &done, Label::kNear); + } // If the object is not a value type, return the object. __ CmpObjectType(input, JS_VALUE_TYPE, map); @@ -2364,8 +2367,11 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { Condition LCodeGen::EmitIsString(Register input, Register temp1, - Label* is_not_string) { - __ JumpIfSmi(input, is_not_string); + Label* is_not_string, + SmiCheck check_needed = INLINE_SMI_CHECK) { + if (check_needed == INLINE_SMI_CHECK) { + __ JumpIfSmi(input, is_not_string); + } Condition cond = masm_->IsObjectStringType(input, temp1, temp1); @@ -2377,7 +2383,12 @@ void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { Register reg = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - Condition true_cond = EmitIsString(reg, temp, instr->FalseLabel(chunk_)); + SmiCheck check_needed = + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + + Condition true_cond = EmitIsString( + reg, temp, instr->FalseLabel(chunk_), check_needed); EmitBranch(instr, true_cond); } @@ -2395,8 +2406,10 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { Register input = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - STATIC_ASSERT(kSmiTag == 0); - __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + if (!instr->hydrogen()->value()->IsHeapObject()) { + STATIC_ASSERT(kSmiTag == 0); + __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + } __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); __ test_b(FieldOperand(temp, Map::kBitFieldOffset), 1 << Map::kIsUndetectable); @@ -2461,7 +2474,9 @@ void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { Register input = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + if (!instr->hydrogen()->value()->IsHeapObject()) { + __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + } __ CmpObjectType(input, TestType(instr->hydrogen()), temp); EmitBranch(instr, BranchCondition(instr->hydrogen())); @@ -2898,9 +2913,9 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { __ mov(target, value); if (instr->hydrogen()->NeedsWriteBarrier()) { - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; Register temp = ToRegister(instr->temp()); int offset = Context::SlotOffset(instr->slot_index()); __ RecordWriteContextSlot(context, @@ -4269,9 +4284,9 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { } // Do the store. - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; Register write_register = object; if (!access.IsInobject()) { @@ -4508,9 +4523,9 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { ASSERT(instr->value()->IsRegister()); Register value = ToRegister(instr->value()); ASSERT(!instr->key()->IsConstantOperand()); - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; // Compute address of modified element and store it into key register. __ lea(key, operand); __ RecordWrite(elements, @@ -5652,9 +5667,11 @@ void LCodeGen::DoCheckSmi(LCheckSmi* instr) { void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { - LOperand* input = instr->value(); - __ test(ToOperand(input), Immediate(kSmiTagMask)); - DeoptimizeIf(zero, instr->environment()); + if (!instr->hydrogen()->value()->IsHeapObject()) { + LOperand* input = instr->value(); + __ test(ToOperand(input), Immediate(kSmiTagMask)); + DeoptimizeIf(zero, instr->environment()); + } } diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index e684527741..d05da8a084 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -357,7 +357,8 @@ class LCodeGen BASE_EMBEDDED { // true and false label should be made, to optimize fallthrough. Condition EmitIsString(Register input, Register temp1, - Label* is_not_string); + Label* is_not_string, + SmiCheck check_needed); // Emits optimized code for %_IsConstructCall(). // Caller should branch on equal condition. diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index bf98242c37..e8ff7666bf 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -2040,7 +2040,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { } -LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { +LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { LOperand* value = UseAtStart(instr->value()); return AssignEnvironment(new(zone()) LCheckNonSmi(value)); } diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 212a49683c..59c6c817c9 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -895,6 +895,7 @@ class LIsStringAndBranch: public LControlInstruction<1, 1> { LOperand* temp() { return temps_[0]; } DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch") + DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch) virtual void PrintDataTo(StringStream* stream); }; @@ -927,6 +928,7 @@ class LIsUndetectableAndBranch: public LControlInstruction<1, 1> { DECLARE_CONCRETE_INSTRUCTION(IsUndetectableAndBranch, "is-undetectable-and-branch") + DECLARE_HYDROGEN_ACCESSOR(IsUndetectableAndBranch) virtual void PrintDataTo(StringStream* stream); }; @@ -2570,6 +2572,7 @@ class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> { LOperand* value() { return inputs_[0]; } DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi") + DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject) }; diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 1d4ab59db9..0a2c3ce554 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -1586,8 +1586,11 @@ void LCodeGen::DoValueOf(LValueOf* instr) { Register result = ToRegister(instr->result()); ASSERT(input.is(result)); Label done; - // If the object is a smi return the object. - __ JumpIfSmi(input, &done, Label::kNear); + + if (!instr->hydrogen()->value()->IsHeapObject()) { + // If the object is a smi return the object. + __ JumpIfSmi(input, &done, Label::kNear); + } // If the object is not a value type, return the object. __ CmpObjectType(input, JS_VALUE_TYPE, kScratchRegister); @@ -2151,8 +2154,12 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { Condition LCodeGen::EmitIsString(Register input, Register temp1, - Label* is_not_string) { - __ JumpIfSmi(input, is_not_string); + Label* is_not_string, + SmiCheck check_needed = INLINE_SMI_CHECK) { + if (check_needed == INLINE_SMI_CHECK) { + __ JumpIfSmi(input, is_not_string); + } + Condition cond = masm_->IsObjectStringType(input, temp1, temp1); return cond; @@ -2163,7 +2170,12 @@ void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) { Register reg = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - Condition true_cond = EmitIsString(reg, temp, instr->FalseLabel(chunk_)); + SmiCheck check_needed = + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + + Condition true_cond = EmitIsString( + reg, temp, instr->FalseLabel(chunk_), check_needed); EmitBranch(instr, true_cond); } @@ -2186,7 +2198,9 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) { Register input = ToRegister(instr->value()); Register temp = ToRegister(instr->temp()); - __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + if (!instr->hydrogen()->value()->IsHeapObject()) { + __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + } __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); __ testb(FieldOperand(temp, Map::kBitFieldOffset), Immediate(1 << Map::kIsUndetectable)); @@ -2230,7 +2244,9 @@ static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) { void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { Register input = ToRegister(instr->value()); - __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + if (!instr->hydrogen()->value()->IsHeapObject()) { + __ JumpIfSmi(input, instr->FalseLabel(chunk_)); + } __ CmpObjectType(input, TestType(instr->hydrogen()), kScratchRegister); EmitBranch(instr, BranchCondition(instr->hydrogen())); @@ -2640,9 +2656,9 @@ void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { __ movq(target, value); if (instr->hydrogen()->NeedsWriteBarrier()) { - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; int offset = Context::SlotOffset(instr->slot_index()); Register scratch = ToRegister(instr->temp()); __ RecordWriteContextSlot(context, @@ -3965,9 +3981,9 @@ void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { } // Do the store. - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; Register write_register = object; if (!access.IsInobject()) { @@ -4206,9 +4222,9 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { ASSERT(instr->value()->IsRegister()); Register value = ToRegister(instr->value()); ASSERT(!instr->key()->IsConstantOperand()); - HType type = instr->hydrogen()->value()->type(); SmiCheck check_needed = - type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; + instr->hydrogen()->value()->IsHeapObject() + ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; // Compute address of modified element and store it into key register. Register key_reg(ToRegister(key)); __ lea(key_reg, operand); @@ -4874,9 +4890,11 @@ void LCodeGen::DoCheckSmi(LCheckSmi* instr) { void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { - LOperand* input = instr->value(); - Condition cc = masm()->CheckSmi(ToRegister(input)); - DeoptimizeIf(cc, instr->environment()); + if (!instr->hydrogen()->value()->IsHeapObject()) { + LOperand* input = instr->value(); + Condition cc = masm()->CheckSmi(ToRegister(input)); + DeoptimizeIf(cc, instr->environment()); + } } diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h index 116f8759b6..c89ec1fd0e 100644 --- a/src/x64/lithium-codegen-x64.h +++ b/src/x64/lithium-codegen-x64.h @@ -312,7 +312,8 @@ class LCodeGen BASE_EMBEDDED { // true and false label should be made, to optimize fallthrough. Condition EmitIsString(Register input, Register temp1, - Label* is_not_string); + Label* is_not_string, + SmiCheck check_needed); // Emits optimized code for %_IsConstructCall(). // Caller should branch on equal condition. diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index afb1c48fc3..a759f16281 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1913,7 +1913,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { } -LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) { +LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) { LOperand* value = UseRegisterAtStart(instr->value()); return AssignEnvironment(new(zone()) LCheckNonSmi(value)); } diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index 48d8b5cfd9..d6edd6de8b 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -2379,6 +2379,7 @@ class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> { LOperand* value() { return inputs_[0]; } DECLARE_CONCRETE_INSTRUCTION(CheckNonSmi, "check-non-smi") + DECLARE_HYDROGEN_ACCESSOR(CheckHeapObject) };