Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 1b7f51944348643086fcf3b1b72d4f56fb227309..7381d022ffed8e18bb11cf933661f8bc0ea46eaa 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -5263,18 +5263,19 @@ static int ComputeLoadStoreFieldIndex(Handle<Map> type, |
} |
+void HGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
+ Handle<Map> map) { |
+ AddInstruction(new(zone()) HCheckNonSmi(object)); |
+ AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
+} |
+ |
+ |
HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
Handle<String> name, |
HValue* value, |
Handle<Map> map, |
- LookupResult* lookup, |
- bool smi_and_map_check) { |
+ LookupResult* lookup) { |
ASSERT(lookup->IsFound()); |
- if (smi_and_map_check) { |
- AddInstruction(new(zone()) HCheckNonSmi(object)); |
- AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
- } |
- |
// If the property does not exist yet, we have to check that it wasn't made |
// readonly or turned into a setter by some meanwhile modifications on the |
// prototype chain. |
@@ -5343,7 +5344,7 @@ HInstruction* HGraphBuilder::BuildCallSetter(HValue* object, |
Handle<Map> map, |
Handle<JSFunction> setter, |
Handle<JSObject> holder) { |
- AddCheckConstantFunction(holder, object, map, true); |
+ AddCheckConstantFunction(holder, object, map); |
AddInstruction(new(zone()) HPushArgument(object)); |
AddInstruction(new(zone()) HPushArgument(value)); |
return new(zone()) HCallConstantFunction(setter, 2); |
@@ -5357,8 +5358,8 @@ HInstruction* HGraphBuilder::BuildStoreNamedMonomorphic(HValue* object, |
// Handle a store to a known field. |
LookupResult lookup(isolate()); |
if (ComputeLoadStoreField(map, name, &lookup, true)) { |
- // true = needs smi and map check. |
- return BuildStoreNamedField(object, name, value, map, &lookup, true); |
+ AddCheckMapsWithTransitions(object, map); |
+ return BuildStoreNamedField(object, name, value, map, &lookup); |
} |
// No luck, do a generic store. |
@@ -5406,7 +5407,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
HInstruction* instr; |
if (count == types->length() && is_monomorphic_field) { |
AddInstruction(new(zone()) HCheckMaps(object, types, zone())); |
- instr = BuildLoadNamedField(object, map, &lookup, false); |
+ instr = BuildLoadNamedField(object, map, &lookup); |
} else { |
HValue* context = environment()->LookupContext(); |
instr = new(zone()) HLoadNamedFieldPolymorphic(context, |
@@ -5449,7 +5450,7 @@ void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
set_current_block(if_true); |
HInstruction* instr; |
CHECK_ALIVE(instr = |
- BuildStoreNamedField(object, name, value, map, &lookup, false)); |
+ BuildStoreNamedField(object, name, value, map, &lookup)); |
instr->set_position(expr->position()); |
// Goto will add the HSimulate for the store. |
AddInstruction(instr); |
@@ -5525,7 +5526,7 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
Handle<JSFunction> setter; |
Handle<JSObject> holder; |
if (LookupSetter(map, name, &setter, &holder)) { |
- AddCheckConstantFunction(holder, object, map, true); |
+ AddCheckConstantFunction(holder, object, map); |
if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) { |
return; |
} |
@@ -5949,13 +5950,7 @@ void HGraphBuilder::VisitThrow(Throw* expr) { |
HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
Handle<Map> map, |
- LookupResult* lookup, |
- bool smi_and_map_check) { |
- if (smi_and_map_check) { |
- AddInstruction(new(zone()) HCheckNonSmi(object)); |
- AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
- } |
- |
+ LookupResult* lookup) { |
int index = lookup->GetLocalFieldIndexFromMap(*map); |
if (index < 0) { |
// Negative property indices are in-object properties, indexed |
@@ -5986,7 +5981,7 @@ HInstruction* HGraphBuilder::BuildCallGetter(HValue* object, |
Handle<Map> map, |
Handle<JSFunction> getter, |
Handle<JSObject> holder) { |
- AddCheckConstantFunction(holder, object, map, true); |
+ AddCheckConstantFunction(holder, object, map); |
AddInstruction(new(zone()) HPushArgument(object)); |
return new(zone()) HCallConstantFunction(getter, 1); |
} |
@@ -6001,13 +5996,13 @@ HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object, |
LookupResult lookup(isolate()); |
map->LookupDescriptor(NULL, *name, &lookup); |
if (lookup.IsField()) { |
- return BuildLoadNamedField(object, map, &lookup, true); |
+ AddCheckMapsWithTransitions(object, map); |
+ return BuildLoadNamedField(object, map, &lookup); |
} |
// Handle a load of a constant known function. |
if (lookup.IsConstantFunction()) { |
- AddInstruction(new(zone()) HCheckNonSmi(object)); |
- AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
+ AddCheckMapsWithTransitions(object, map); |
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
return new(zone()) HConstant(function, Representation::Tagged()); |
} |
@@ -6018,11 +6013,10 @@ HInstruction* HGraphBuilder::BuildLoadNamedMonomorphic(HValue* object, |
Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
Handle<JSObject> holder(lookup.holder()); |
Handle<Map> holder_map(holder->map()); |
- AddInstruction(new(zone()) HCheckNonSmi(object)); |
- AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
+ AddCheckMapsWithTransitions(object, map); |
HInstruction* holder_value = |
AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder)); |
- return BuildLoadNamedField(holder_value, holder_map, &lookup, false); |
+ return BuildLoadNamedField(holder_value, holder_map, &lookup); |
} |
// No luck, do a generic load. |
@@ -6658,7 +6652,7 @@ void HGraphBuilder::VisitProperty(Property* expr) { |
Handle<JSFunction> getter; |
Handle<JSObject> holder; |
if (LookupGetter(map, name, &getter, &holder)) { |
- AddCheckConstantFunction(holder, Top(), map, true); |
+ AddCheckConstantFunction(holder, Top(), map); |
if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; |
AddInstruction(new(zone()) HPushArgument(Pop())); |
instr = new(zone()) HCallConstantFunction(getter, 1); |
@@ -6698,22 +6692,23 @@ void HGraphBuilder::VisitProperty(Property* expr) { |
} |
+void HGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
+ Handle<Map> receiver_map) { |
+ if (!holder.is_null()) { |
+ AddInstruction(new(zone()) HCheckPrototypeMaps( |
+ Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); |
+ } |
+} |
+ |
+ |
void HGraphBuilder::AddCheckConstantFunction(Handle<JSObject> holder, |
HValue* receiver, |
- Handle<Map> receiver_map, |
- bool smi_and_map_check) { |
+ Handle<Map> receiver_map) { |
// Constant functions have the nice property that the map will change if they |
// are overwritten. Therefore it is enough to check the map of the holder and |
// its prototypes. |
- if (smi_and_map_check) { |
- AddInstruction(new(zone()) HCheckNonSmi(receiver)); |
- AddInstruction(HCheckMaps::NewWithTransitions(receiver, receiver_map, |
- zone())); |
- } |
- if (!holder.is_null()) { |
- AddInstruction(new(zone()) HCheckPrototypeMaps( |
- Handle<JSObject>(JSObject::cast(receiver_map->prototype())), holder)); |
- } |
+ AddCheckMapsWithTransitions(receiver, receiver_map); |
+ AddCheckPrototypeMaps(holder, receiver_map); |
} |
@@ -6795,7 +6790,7 @@ void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
set_current_block(if_true); |
expr->ComputeTarget(map, name); |
- AddCheckConstantFunction(expr->holder(), receiver, map, false); |
+ AddCheckPrototypeMaps(expr->holder(), map); |
if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
Handle<JSFunction> caller = info()->closure(); |
SmartArrayPointer<char> caller_name = |
@@ -7350,7 +7345,7 @@ bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, |
case kMathCos: |
case kMathTan: |
if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
- AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
+ AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
HValue* argument = Pop(); |
HValue* context = environment()->LookupContext(); |
Drop(1); // Receiver. |
@@ -7363,7 +7358,7 @@ bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, |
break; |
case kMathPow: |
if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
- AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
+ AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
HValue* right = Pop(); |
HValue* left = Pop(); |
Pop(); // Pop receiver. |
@@ -7405,7 +7400,7 @@ bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, |
break; |
case kMathRandom: |
if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { |
- AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
+ AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
Drop(1); // Receiver. |
HValue* context = environment()->LookupContext(); |
HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
@@ -7418,7 +7413,7 @@ bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, |
case kMathMax: |
case kMathMin: |
if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
- AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
+ AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
HValue* right = Pop(); |
HValue* left = Pop(); |
Drop(1); // Receiver. |
@@ -7467,7 +7462,7 @@ bool HGraphBuilder::TryCallApply(Call* expr) { |
VisitForValue(prop->obj()); |
if (HasStackOverflow() || current_block() == NULL) return true; |
HValue* function = Top(); |
- AddCheckConstantFunction(expr->holder(), function, function_map, true); |
+ AddCheckConstantFunction(expr->holder(), function, function_map); |
Drop(1); |
VisitForValue(args->at(0)); |
@@ -7586,7 +7581,7 @@ void HGraphBuilder::VisitCall(Call* expr) { |
call = PreProcessCall( |
new(zone()) HCallNamed(context, name, argument_count)); |
} else { |
- AddCheckConstantFunction(expr->holder(), receiver, receiver_map, true); |
+ AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
if (TryInlineCall(expr)) return; |
call = PreProcessCall( |
@@ -8660,10 +8655,8 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
// Can we get away with map check and not instance type check? |
Handle<Map> map = oracle()->GetCompareMap(expr); |
if (!map.is_null()) { |
- AddInstruction(new(zone()) HCheckNonSmi(left)); |
- AddInstruction(HCheckMaps::NewWithTransitions(left, map, zone())); |
- AddInstruction(new(zone()) HCheckNonSmi(right)); |
- AddInstruction(HCheckMaps::NewWithTransitions(right, map, zone())); |
+ AddCheckMapsWithTransitions(left, map); |
+ AddCheckMapsWithTransitions(right, map); |
HCompareObjectEqAndBranch* result = |
new(zone()) HCompareObjectEqAndBranch(left, right); |
result->set_position(expr->position()); |