OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 4016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4027 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); | 4027 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); |
4028 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. | 4028 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. |
4029 return new(zone()) HLoadKeyedFastElement(elements, checked_key); | 4029 return new(zone()) HLoadKeyedFastElement(elements, checked_key); |
4030 } | 4030 } |
4031 } | 4031 } |
4032 | 4032 |
4033 | 4033 |
4034 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, | 4034 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
4035 HValue* key, | 4035 HValue* key, |
4036 HValue* val, | 4036 HValue* val, |
4037 Expression* expr, | 4037 Handle<Map> map, |
4038 bool is_store) { | 4038 bool is_store) { |
4039 ASSERT(expr->IsMonomorphic()); | |
4040 Handle<Map> map = expr->GetMonomorphicReceiverType(); | |
4041 AddInstruction(new(zone()) HCheckNonSmi(object)); | |
4042 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); | 4039 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); |
4043 bool fast_smi_only_elements = map->has_fast_smi_only_elements(); | 4040 bool fast_smi_only_elements = map->has_fast_smi_only_elements(); |
4044 bool fast_elements = map->has_fast_elements(); | 4041 bool fast_elements = map->has_fast_elements(); |
4045 bool fast_double_elements = map->has_fast_double_elements(); | 4042 bool fast_double_elements = map->has_fast_double_elements(); |
4046 if (!fast_smi_only_elements && | 4043 if (!fast_smi_only_elements && |
4047 !fast_elements && | 4044 !fast_elements && |
4048 !fast_double_elements && | 4045 !fast_double_elements && |
4049 !map->has_external_array_elements()) { | 4046 !map->has_external_array_elements()) { |
4050 return is_store ? BuildStoreKeyedGeneric(object, key, val) | 4047 return is_store ? BuildStoreKeyedGeneric(object, key, val) |
4051 : BuildLoadKeyedGeneric(object, key); | 4048 : BuildLoadKeyedGeneric(object, key); |
(...skipping 29 matching lines...) Expand all Loading... |
4081 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, | 4078 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
4082 HValue* key, | 4079 HValue* key, |
4083 HValue* val, | 4080 HValue* val, |
4084 Expression* prop, | 4081 Expression* prop, |
4085 int ast_id, | 4082 int ast_id, |
4086 int position, | 4083 int position, |
4087 bool is_store, | 4084 bool is_store, |
4088 bool* has_side_effects) { | 4085 bool* has_side_effects) { |
4089 *has_side_effects = false; | 4086 *has_side_effects = false; |
4090 AddInstruction(new(zone()) HCheckNonSmi(object)); | 4087 AddInstruction(new(zone()) HCheckNonSmi(object)); |
4091 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); | |
4092 SmallMapList* maps = prop->GetReceiverTypes(); | 4088 SmallMapList* maps = prop->GetReceiverTypes(); |
4093 bool todo_external_array = false; | 4089 bool todo_external_array = false; |
4094 | 4090 |
4095 static const int kNumElementTypes = kElementsKindCount; | 4091 static const int kNumElementTypes = kElementsKindCount; |
4096 bool type_todo[kNumElementTypes]; | 4092 bool type_todo[kNumElementTypes]; |
4097 for (int i = 0; i < kNumElementTypes; ++i) { | 4093 for (int i = 0; i < kNumElementTypes; ++i) { |
4098 type_todo[i] = false; | 4094 type_todo[i] = false; |
4099 } | 4095 } |
4100 | 4096 |
4101 // Elements_kind transition support. | 4097 // Elements_kind transition support. |
(...skipping 11 matching lines...) Expand all Loading... |
4113 } | 4109 } |
4114 // Get transition target for each map (NULL == no transition). | 4110 // Get transition target for each map (NULL == no transition). |
4115 for (int i = 0; i < maps->length(); ++i) { | 4111 for (int i = 0; i < maps->length(); ++i) { |
4116 Handle<Map> map = maps->at(i); | 4112 Handle<Map> map = maps->at(i); |
4117 Map* transitioned_map = | 4113 Map* transitioned_map = |
4118 map->FindTransitionedMap(&possible_transitioned_maps); | 4114 map->FindTransitionedMap(&possible_transitioned_maps); |
4119 transition_target.Add(transitioned_map); | 4115 transition_target.Add(transitioned_map); |
4120 } | 4116 } |
4121 } | 4117 } |
4122 | 4118 |
| 4119 int num_untransitionable_maps = 0; |
| 4120 Handle<Map> untransitionable_map; |
4123 for (int i = 0; i < maps->length(); ++i) { | 4121 for (int i = 0; i < maps->length(); ++i) { |
4124 Handle<Map> map = maps->at(i); | 4122 Handle<Map> map = maps->at(i); |
4125 ASSERT(map->IsMap()); | 4123 ASSERT(map->IsMap()); |
4126 ASSERT(!is_store || (transition_target.length() == maps->length())); | 4124 ASSERT(!is_store || (transition_target.length() == maps->length())); |
4127 if (is_store && transition_target.at(i) != NULL) { | 4125 if (is_store && transition_target.at(i) != NULL) { |
4128 object = AddInstruction(new(zone()) HTransitionElementsKind( | 4126 object = AddInstruction(new(zone()) HTransitionElementsKind( |
4129 object, map, Handle<Map>(transition_target.at(i)))); | 4127 object, map, Handle<Map>(transition_target.at(i)))); |
4130 } else { | 4128 } else { |
4131 type_todo[map->elements_kind()] = true; | 4129 type_todo[map->elements_kind()] = true; |
4132 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { | 4130 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { |
4133 todo_external_array = true; | 4131 todo_external_array = true; |
4134 } | 4132 } |
| 4133 num_untransitionable_maps++; |
| 4134 untransitionable_map = map; |
4135 } | 4135 } |
4136 } | 4136 } |
4137 | 4137 |
| 4138 // If only one map is left after transitioning, handle this case |
| 4139 // monomorphically. |
| 4140 if (num_untransitionable_maps == 1) { |
| 4141 HInstruction* instr = AddInstruction(BuildMonomorphicElementAccess( |
| 4142 object, key, val, untransitionable_map, is_store)); |
| 4143 *has_side_effects |= instr->HasSideEffects(); |
| 4144 instr->set_position(position); |
| 4145 return is_store ? NULL : instr; |
| 4146 } |
| 4147 |
| 4148 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); |
4138 HBasicBlock* join = graph()->CreateBasicBlock(); | 4149 HBasicBlock* join = graph()->CreateBasicBlock(); |
4139 | 4150 |
4140 HInstruction* elements_kind_instr = | 4151 HInstruction* elements_kind_instr = |
4141 AddInstruction(new(zone()) HElementsKind(object)); | 4152 AddInstruction(new(zone()) HElementsKind(object)); |
4142 HCompareConstantEqAndBranch* elements_kind_branch = NULL; | 4153 HCompareConstantEqAndBranch* elements_kind_branch = NULL; |
4143 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 4154 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
4144 HLoadExternalArrayPointer* external_elements = NULL; | 4155 HLoadExternalArrayPointer* external_elements = NULL; |
4145 HInstruction* checked_key = NULL; | 4156 HInstruction* checked_key = NULL; |
4146 | 4157 |
4147 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS, | 4158 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS, |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4259 HValue* key, | 4270 HValue* key, |
4260 HValue* val, | 4271 HValue* val, |
4261 Expression* expr, | 4272 Expression* expr, |
4262 int ast_id, | 4273 int ast_id, |
4263 int position, | 4274 int position, |
4264 bool is_store, | 4275 bool is_store, |
4265 bool* has_side_effects) { | 4276 bool* has_side_effects) { |
4266 ASSERT(!expr->IsPropertyName()); | 4277 ASSERT(!expr->IsPropertyName()); |
4267 HInstruction* instr = NULL; | 4278 HInstruction* instr = NULL; |
4268 if (expr->IsMonomorphic()) { | 4279 if (expr->IsMonomorphic()) { |
4269 instr = BuildMonomorphicElementAccess(obj, key, val, expr, is_store); | 4280 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 4281 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
| 4282 instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store); |
4270 } else if (expr->GetReceiverTypes() != NULL && | 4283 } else if (expr->GetReceiverTypes() != NULL && |
4271 !expr->GetReceiverTypes()->is_empty()) { | 4284 !expr->GetReceiverTypes()->is_empty()) { |
4272 return HandlePolymorphicElementAccess( | 4285 return HandlePolymorphicElementAccess( |
4273 obj, key, val, expr, ast_id, position, is_store, has_side_effects); | 4286 obj, key, val, expr, ast_id, position, is_store, has_side_effects); |
4274 } else { | 4287 } else { |
4275 if (is_store) { | 4288 if (is_store) { |
4276 instr = BuildStoreKeyedGeneric(obj, key, val); | 4289 instr = BuildStoreKeyedGeneric(obj, key, val); |
4277 } else { | 4290 } else { |
4278 instr = BuildLoadKeyedGeneric(obj, key); | 4291 instr = BuildLoadKeyedGeneric(obj, key); |
4279 } | 4292 } |
(...skipping 2723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7003 } | 7016 } |
7004 } | 7017 } |
7005 | 7018 |
7006 #ifdef DEBUG | 7019 #ifdef DEBUG |
7007 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 7020 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
7008 if (allocator_ != NULL) allocator_->Verify(); | 7021 if (allocator_ != NULL) allocator_->Verify(); |
7009 #endif | 7022 #endif |
7010 } | 7023 } |
7011 | 7024 |
7012 } } // namespace v8::internal | 7025 } } // namespace v8::internal |
OLD | NEW |