Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 51ae7f5a44c29fc4b69f66651b95fcfef7a6f2fa..9dcd90e9b7181ed3038b5e306a970a3c5f1b5028 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -6613,6 +6613,8 @@ void HGraphBuilder::VisitProperty(Property* expr) { |
| HInstruction* instr = NULL; |
| if (expr->AsProperty()->IsArrayLength()) { |
| + // Note that in the monomorphic case IsArrayLength() is false because we |
| + // handle that it with a regular property load IC. |
| HValue* array = Pop(); |
| AddInstruction(new(zone()) HCheckNonSmi(array)); |
| HInstruction* mapcheck = |
| @@ -6648,23 +6650,67 @@ void HGraphBuilder::VisitProperty(Property* expr) { |
| map = types->first(); |
| if (map->is_dictionary_map()) monomorphic = false; |
| } |
| - if (monomorphic) { |
| - Handle<JSFunction> getter; |
| - Handle<JSObject> holder; |
| - if (LookupGetter(map, name, &getter, &holder)) { |
| - AddCheckConstantFunction(holder, Top(), map); |
| - if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; |
| - AddInstruction(new(zone()) HPushArgument(Pop())); |
| - instr = new(zone()) HCallConstantFunction(getter, 1); |
| + |
| + // Try to see if this is an array length access. |
| + if (name->Equals(isolate()->heap()->length_symbol())) { |
| + bool is_array = false; |
| + bool fast_mode = false; |
| + bool map_mode = false; |
| + HInstruction* mapcheck = NULL; |
| + |
| + if (expr->IsMonomorphic()) { |
| + if (map->instance_type() == JS_ARRAY_TYPE) { |
| + is_array = true; |
| + map_mode = true; |
| + fast_mode = IsFastElementsKind(map->elements_kind()); |
| + } |
| } else { |
| - instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); |
| + map_mode = false; |
| + fast_mode = false; |
|
Jakob Kummerow
2012/11/16 12:57:10
Why do you always set this to false? You could do
Massi
2012/11/19 12:26:15
Because in this case I will emit an instance check
Jakob Kummerow
2012/11/19 12:58:47
Makes sense. Please add a comment to that effect.
|
| + is_array = true; |
| + for (int i = 0; i < types->length(); i++) { |
| + Handle<Map> current_map = types->at(i); |
| + if (!current_map->instance_type() == JS_ARRAY_TYPE) { |
| + is_array = false; |
| + break; |
| + } |
| + } |
| + } |
| + |
| + // It is an array length access so we produce a HJSArrayLength. |
| + if (is_array) { |
| + HValue* array = Pop(); |
| + AddInstruction(new(zone()) HCheckNonSmi(array)); |
| + mapcheck = map_mode ? |
| + HInstruction::cast(new(zone()) HCheckMaps(array, map, zone())) : |
| + HInstruction::cast( |
| + HCheckInstanceType::NewIsJSArray(array, zone())); |
| + AddInstruction(mapcheck); |
| + instr = new(zone()) HJSArrayLength( |
| + array, mapcheck, fast_mode ? HType::Smi() : HType::Tagged()); |
| } |
| - } else if (types != NULL && types->length() > 1) { |
| - return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); |
| - } else { |
| - instr = BuildLoadNamedGeneric(Pop(), name, expr); |
| } |
| + // We cannot know if it was an array length access so we handle it as |
| + // a regular property access. |
| + if (instr == NULL) { |
| + if (monomorphic) { |
| + Handle<JSFunction> getter; |
| + Handle<JSObject> holder; |
| + if (LookupGetter(map, name, &getter, &holder)) { |
| + AddCheckConstantFunction(holder, Top(), map); |
| + if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; |
| + AddInstruction(new(zone()) HPushArgument(Pop())); |
| + instr = new(zone()) HCallConstantFunction(getter, 1); |
| + } else { |
| + instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map); |
| + } |
| + } else if (types != NULL && types->length() > 1) { |
| + return HandlePolymorphicLoadNamedField(expr, Pop(), types, name); |
| + } else { |
| + instr = BuildLoadNamedGeneric(Pop(), name, expr); |
| + } |
| + } |
| } else { |
| CHECK_ALIVE(VisitForValue(expr->key())); |