Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index 14feb5f1329eb89b3a738525e5640057d39a4202..51aa62cff52d69aa7003b73df966fdce79ae8ee2 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -1053,6 +1053,12 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| elements_kind, is_store); |
| } |
|
danno
2013/03/22 14:25:40
nit: two spaces before function
|
| +HInstruction* HGraphBuilder::BuildFastArrayLengthLoad(HValue* object, |
| + HValue* typecheck) { |
| + Zone* zone = this->zone(); |
| + return new (zone) HJSArrayLength(object, typecheck, HType::Smi()); |
| +} |
| + |
| HValue* HGraphBuilder::BuildAllocateElements(HContext* context, |
| ElementsKind kind, |
| @@ -5996,6 +6002,11 @@ static int ComputeLoadStoreFieldIndex(Handle<Map> type, |
| } |
| +void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { |
| + AddInstruction(new(zone()) HCheckNonSmi(object)); |
| + AddInstruction(new(zone()) HCheckMaps(object, map, zone())); |
| +} |
| + |
|
danno
2013/03/22 14:25:40
nit: two spaces after function
|
| void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
| Handle<Map> map) { |
| AddInstruction(new(zone()) HCheckNonSmi(object)); |
| @@ -6106,6 +6117,25 @@ HInstruction* HOptimizedGraphBuilder::BuildStoreNamedMonomorphic( |
| return BuildStoreNamedGeneric(object, name, value); |
| } |
|
danno
2013/03/22 14:25:40
nit: two spaces between functions
|
| +bool HOptimizedGraphBuilder::HandlePolymorphicArrayLengthLoad( |
| + Property* expr, |
| + HValue* object, |
| + SmallMapList* types, |
| + Handle<String> name) { |
| + if (!name->Equals(isolate()->heap()->length_string())) return false; |
| + |
| + for (int i = 0; i < types->length(); i++) { |
| + if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false; |
| + } |
| + |
| + AddInstruction(new(zone()) HCheckNonSmi(object)); |
| + HInstruction* typecheck = |
| + AddInstruction(HCheckInstanceType::NewIsJSArray(object, zone())); |
| + HInstruction* instr = BuildFastArrayLengthLoad(object, typecheck); |
| + instr->set_position(expr->position()); |
| + ast_context()->ReturnInstruction(instr, expr->id()); |
| + return true; |
| +} |
|
danno
2013/03/22 14:25:40
nit: two spaces between functions.
|
| void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| Property* expr, |
| @@ -6116,6 +6146,10 @@ void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| int previous_field_offset = 0; |
| bool previous_field_is_in_object = false; |
| bool is_monomorphic_field = true; |
| + |
| + if (HandlePolymorphicArrayLengthLoad(expr, object, types, name)) |
| + return; |
| + |
| Handle<Map> map; |
| LookupResult lookup(isolate()); |
| for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
| @@ -6751,16 +6785,25 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( |
| Handle<Map> map) { |
| // Handle a load from a known field. |
| ASSERT(!map->is_dictionary_map()); |
| + |
| + // Handle access to various length properties |
| + if (name->Equals(isolate()->heap()->length_string())) { |
| + if (map->instance_type() == JS_ARRAY_TYPE) { |
| + AddCheckMapsWithTransitions(object, map); |
| + return BuildFastArrayLengthLoad(object, NULL); |
| + } |
| + } |
| + |
| LookupResult lookup(isolate()); |
| map->LookupDescriptor(NULL, *name, &lookup); |
| if (lookup.IsField()) { |
| - AddCheckMapsWithTransitions(object, map); |
| + AddCheckMap(object, map); |
| return BuildLoadNamedField(object, map, &lookup); |
| } |
| // Handle a load of a constant known function. |
| if (lookup.IsConstantFunction()) { |
| - AddCheckMapsWithTransitions(object, map); |
| + AddCheckMap(object, map); |
| Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| return new(zone()) HConstant(function, Representation::Tagged()); |
| } |
| @@ -6771,7 +6814,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( |
| Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| Handle<JSObject> holder(lookup.holder()); |
| Handle<Map> holder_map(holder->map()); |
| - AddCheckMapsWithTransitions(object, map); |
| + AddCheckMap(object, map); |
| HInstruction* holder_value = AddInstruction( |
| new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
| return BuildLoadNamedField(holder_value, holder_map, &lookup); |
| @@ -6782,7 +6825,7 @@ HInstruction* HOptimizedGraphBuilder::BuildLoadNamedMonomorphic( |
| Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
| Handle<JSObject> holder(lookup.holder()); |
| Handle<Map> holder_map(holder->map()); |
| - AddCheckMapsWithTransitions(object, map); |
| + AddCheckMap(object, map); |
| AddInstruction(new(zone()) HCheckPrototypeMaps(prototype, holder, zone())); |
| Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*holder_map)); |
| return new(zone()) HConstant(function, Representation::Tagged()); |
| @@ -7237,13 +7280,7 @@ void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
| CHECK_ALIVE(VisitForValue(expr->obj())); |
| HInstruction* instr = NULL; |
| - if (expr->AsProperty()->IsArrayLength()) { |
| - HValue* array = Pop(); |
| - AddInstruction(new(zone()) HCheckNonSmi(array)); |
| - HInstruction* mapcheck = |
| - AddInstruction(HCheckInstanceType::NewIsJSArray(array, zone())); |
| - instr = new(zone()) HJSArrayLength(array, mapcheck); |
| - } else if (expr->IsStringLength()) { |
| + if (expr->IsStringLength()) { |
| HValue* string = Pop(); |
| AddInstruction(new(zone()) HCheckNonSmi(string)); |
| AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |