Avoid Unnecessary Smi Checks

BUG=
R=ulan@chromium.org

Review URL: https://codereview.chromium.org/16026023

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15344 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
olivf@chromium.org 2013-06-26 17:37:55 +00:00
parent df181f2c11
commit 21cd74eaa2
16 changed files with 149 additions and 93 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Map> type,
void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) {
BuildCheckNonSmi(object);
BuildCheckHeapObject(object);
AddInstruction(HCheckMaps::New(object, map, zone()));
}
void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object,
Handle<Map> 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);

View File

@ -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> map);
// Building common constructs

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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