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