OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 5523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5534 | 5534 |
5535 Handle<FixedArray> properties(boilerplate->properties()); | 5535 Handle<FixedArray> properties(boilerplate->properties()); |
5536 if (properties->length() > 0) { | 5536 if (properties->length() > 0) { |
5537 return false; | 5537 return false; |
5538 } else { | 5538 } else { |
5539 Handle<DescriptorArray> descriptors( | 5539 Handle<DescriptorArray> descriptors( |
5540 boilerplate->map()->instance_descriptors()); | 5540 boilerplate->map()->instance_descriptors()); |
5541 int limit = boilerplate->map()->NumberOfOwnDescriptors(); | 5541 int limit = boilerplate->map()->NumberOfOwnDescriptors(); |
5542 for (int i = 0; i < limit; i++) { | 5542 for (int i = 0; i < limit; i++) { |
5543 PropertyDetails details = descriptors->GetDetails(i); | 5543 PropertyDetails details = descriptors->GetDetails(i); |
5544 if (details.type() != FIELD) continue; | 5544 if (details.type() != DATA_FIELD) continue; |
5545 if ((*max_properties)-- == 0) return false; | 5545 if ((*max_properties)-- == 0) return false; |
5546 FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i); | 5546 FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i); |
5547 if (boilerplate->IsUnboxedDoubleField(field_index)) continue; | 5547 if (boilerplate->IsUnboxedDoubleField(field_index)) continue; |
5548 Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), | 5548 Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), |
5549 isolate); | 5549 isolate); |
5550 if (value->IsJSObject()) { | 5550 if (value->IsJSObject()) { |
5551 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 5551 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
5552 if (!IsFastLiteral(value_object, | 5552 if (!IsFastLiteral(value_object, |
5553 max_depth - 1, | 5553 max_depth - 1, |
5554 max_properties)) { | 5554 max_properties)) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5651 Handle<String> name = property->key()->AsPropertyName(); | 5651 Handle<String> name = property->key()->AsPropertyName(); |
5652 HInstruction* store; | 5652 HInstruction* store; |
5653 if (map.is_null()) { | 5653 if (map.is_null()) { |
5654 // If we don't know the monomorphic type, do a generic store. | 5654 // If we don't know the monomorphic type, do a generic store. |
5655 CHECK_ALIVE(store = BuildNamedGeneric( | 5655 CHECK_ALIVE(store = BuildNamedGeneric( |
5656 STORE, NULL, literal, name, value)); | 5656 STORE, NULL, literal, name, value)); |
5657 } else { | 5657 } else { |
5658 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5658 PropertyAccessInfo info(this, STORE, ToType(map), name); |
5659 if (info.CanAccessMonomorphic()) { | 5659 if (info.CanAccessMonomorphic()) { |
5660 HValue* checked_literal = Add<HCheckMaps>(literal, map); | 5660 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
5661 DCHECK(!info.IsAccessor()); | 5661 DCHECK(!info.IsAccessorConstant()); |
5662 store = BuildMonomorphicAccess( | 5662 store = BuildMonomorphicAccess( |
5663 &info, literal, checked_literal, value, | 5663 &info, literal, checked_literal, value, |
5664 BailoutId::None(), BailoutId::None()); | 5664 BailoutId::None(), BailoutId::None()); |
5665 } else { | 5665 } else { |
5666 CHECK_ALIVE(store = BuildNamedGeneric( | 5666 CHECK_ALIVE(store = BuildNamedGeneric( |
5667 STORE, NULL, literal, name, value)); | 5667 STORE, NULL, literal, name, value)); |
5668 } | 5668 } |
5669 } | 5669 } |
5670 AddInstruction(store); | 5670 AddInstruction(store); |
5671 DCHECK(store->HasObservableSideEffects()); | 5671 DCHECK(store->HasObservableSideEffects()); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5963 | 5963 |
5964 if (!IsFound()) { | 5964 if (!IsFound()) { |
5965 return (!info->IsFound() || info->has_holder()) && | 5965 return (!info->IsFound() || info->has_holder()) && |
5966 map()->prototype() == info->map()->prototype(); | 5966 map()->prototype() == info->map()->prototype(); |
5967 } | 5967 } |
5968 | 5968 |
5969 // Mismatch if the other access info found the property in the prototype | 5969 // Mismatch if the other access info found the property in the prototype |
5970 // chain. | 5970 // chain. |
5971 if (info->has_holder()) return false; | 5971 if (info->has_holder()) return false; |
5972 | 5972 |
5973 if (IsAccessor()) { | 5973 if (IsAccessorConstant()) { |
5974 return accessor_.is_identical_to(info->accessor_) && | 5974 return accessor_.is_identical_to(info->accessor_) && |
5975 api_holder_.is_identical_to(info->api_holder_); | 5975 api_holder_.is_identical_to(info->api_holder_); |
5976 } | 5976 } |
5977 | 5977 |
5978 if (IsConstant()) { | 5978 if (IsDataConstant()) { |
5979 return constant_.is_identical_to(info->constant_); | 5979 return constant_.is_identical_to(info->constant_); |
5980 } | 5980 } |
5981 | 5981 |
5982 DCHECK(IsField()); | 5982 DCHECK(IsDataField()); |
5983 if (!info->IsField()) return false; | 5983 if (!info->IsDataField()) return false; |
5984 | 5984 |
5985 Representation r = access_.representation(); | 5985 Representation r = access_.representation(); |
5986 if (IsLoad()) { | 5986 if (IsLoad()) { |
5987 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; | 5987 if (!info->access_.representation().IsCompatibleForLoad(r)) return false; |
5988 } else { | 5988 } else { |
5989 if (!info->access_.representation().IsCompatibleForStore(r)) return false; | 5989 if (!info->access_.representation().IsCompatibleForStore(r)) return false; |
5990 } | 5990 } |
5991 if (info->access_.offset() != access_.offset()) return false; | 5991 if (info->access_.offset() != access_.offset()) return false; |
5992 if (info->access_.IsInobject() != access_.IsInobject()) return false; | 5992 if (info->access_.IsInobject() != access_.IsInobject()) return false; |
5993 if (IsLoad()) { | 5993 if (IsLoad()) { |
(...skipping 26 matching lines...) Expand all Loading... |
6020 map()->LookupDescriptor(NULL, *name_, &lookup_); | 6020 map()->LookupDescriptor(NULL, *name_, &lookup_); |
6021 return LoadResult(map()); | 6021 return LoadResult(map()); |
6022 } | 6022 } |
6023 | 6023 |
6024 | 6024 |
6025 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { | 6025 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) { |
6026 if (!IsLoad() && IsProperty() && IsReadOnly()) { | 6026 if (!IsLoad() && IsProperty() && IsReadOnly()) { |
6027 return false; | 6027 return false; |
6028 } | 6028 } |
6029 | 6029 |
6030 if (IsField()) { | 6030 if (IsDataField()) { |
6031 // Construct the object field access. | 6031 // Construct the object field access. |
6032 int index = GetLocalFieldIndexFromMap(map); | 6032 int index = GetLocalFieldIndexFromMap(map); |
6033 access_ = HObjectAccess::ForField(map, index, representation(), name_); | 6033 access_ = HObjectAccess::ForField(map, index, representation(), name_); |
6034 | 6034 |
6035 // Load field map for heap objects. | 6035 // Load field map for heap objects. |
6036 LoadFieldMaps(map); | 6036 LoadFieldMaps(map); |
6037 } else if (IsAccessor()) { | 6037 } else if (IsAccessorConstant()) { |
6038 Handle<Object> accessors = GetAccessorsFromMap(map); | 6038 Handle<Object> accessors = GetAccessorsFromMap(map); |
6039 if (!accessors->IsAccessorPair()) return false; | 6039 if (!accessors->IsAccessorPair()) return false; |
6040 Object* raw_accessor = | 6040 Object* raw_accessor = |
6041 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() | 6041 IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter() |
6042 : Handle<AccessorPair>::cast(accessors)->setter(); | 6042 : Handle<AccessorPair>::cast(accessors)->setter(); |
6043 if (!raw_accessor->IsJSFunction()) return false; | 6043 if (!raw_accessor->IsJSFunction()) return false; |
6044 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); | 6044 Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor)); |
6045 if (accessor->shared()->IsApiFunction()) { | 6045 if (accessor->shared()->IsApiFunction()) { |
6046 CallOptimization call_optimization(accessor); | 6046 CallOptimization call_optimization(accessor); |
6047 if (call_optimization.is_simple_api_call()) { | 6047 if (call_optimization.is_simple_api_call()) { |
6048 CallOptimization::HolderLookup holder_lookup; | 6048 CallOptimization::HolderLookup holder_lookup; |
6049 Handle<Map> receiver_map = this->map(); | 6049 Handle<Map> receiver_map = this->map(); |
6050 api_holder_ = call_optimization.LookupHolderOfExpectedType( | 6050 api_holder_ = call_optimization.LookupHolderOfExpectedType( |
6051 receiver_map, &holder_lookup); | 6051 receiver_map, &holder_lookup); |
6052 } | 6052 } |
6053 } | 6053 } |
6054 accessor_ = accessor; | 6054 accessor_ = accessor; |
6055 } else if (IsConstant()) { | 6055 } else if (IsDataConstant()) { |
6056 constant_ = GetConstantFromMap(map); | 6056 constant_ = GetConstantFromMap(map); |
6057 } | 6057 } |
6058 | 6058 |
6059 return true; | 6059 return true; |
6060 } | 6060 } |
6061 | 6061 |
6062 | 6062 |
6063 void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( | 6063 void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps( |
6064 Handle<Map> map) { | 6064 Handle<Map> map) { |
6065 // Clear any previously collected field maps/type. | 6065 // Clear any previously collected field maps/type. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6124 if (this->map()->function_with_prototype() && | 6124 if (this->map()->function_with_prototype() && |
6125 !this->map()->has_non_instance_prototype() && | 6125 !this->map()->has_non_instance_prototype() && |
6126 name_.is_identical_to(isolate()->factory()->prototype_string())) { | 6126 name_.is_identical_to(isolate()->factory()->prototype_string())) { |
6127 return IsLoad(); | 6127 return IsLoad(); |
6128 } | 6128 } |
6129 if (!LookupDescriptor()) return false; | 6129 if (!LookupDescriptor()) return false; |
6130 if (IsFound()) return IsLoad() || !IsReadOnly(); | 6130 if (IsFound()) return IsLoad() || !IsReadOnly(); |
6131 if (!LookupInPrototypes()) return false; | 6131 if (!LookupInPrototypes()) return false; |
6132 if (IsLoad()) return true; | 6132 if (IsLoad()) return true; |
6133 | 6133 |
6134 if (IsAccessor()) return true; | 6134 if (IsAccessorConstant()) return true; |
6135 Handle<Map> map = this->map(); | 6135 Handle<Map> map = this->map(); |
6136 map->LookupTransition(NULL, *name_, NONE, &lookup_); | 6136 map->LookupTransition(NULL, *name_, NONE, &lookup_); |
6137 if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) { | 6137 if (lookup_.IsTransitionToDataField() && map->unused_property_fields() > 0) { |
6138 // Construct the object field access. | 6138 // Construct the object field access. |
6139 int descriptor = transition()->LastAdded(); | 6139 int descriptor = transition()->LastAdded(); |
6140 int index = | 6140 int index = |
6141 transition()->instance_descriptors()->GetFieldIndex(descriptor) - | 6141 transition()->instance_descriptors()->GetFieldIndex(descriptor) - |
6142 map->inobject_properties(); | 6142 map->inobject_properties(); |
6143 PropertyDetails details = | 6143 PropertyDetails details = |
6144 transition()->instance_descriptors()->GetDetails(descriptor); | 6144 transition()->instance_descriptors()->GetDetails(descriptor); |
6145 Representation representation = details.representation(); | 6145 Representation representation = details.representation(); |
6146 access_ = HObjectAccess::ForField(map, index, representation, name_); | 6146 access_ = HObjectAccess::ForField(map, index, representation, name_); |
6147 | 6147 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6231 if (info->has_holder()) { | 6231 if (info->has_holder()) { |
6232 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 6232 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
6233 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 6233 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
6234 } | 6234 } |
6235 | 6235 |
6236 if (!info->IsFound()) { | 6236 if (!info->IsFound()) { |
6237 DCHECK(info->IsLoad()); | 6237 DCHECK(info->IsLoad()); |
6238 return graph()->GetConstantUndefined(); | 6238 return graph()->GetConstantUndefined(); |
6239 } | 6239 } |
6240 | 6240 |
6241 if (info->IsField()) { | 6241 if (info->IsDataField()) { |
6242 if (info->IsLoad()) { | 6242 if (info->IsLoad()) { |
6243 return BuildLoadNamedField(info, checked_holder); | 6243 return BuildLoadNamedField(info, checked_holder); |
6244 } else { | 6244 } else { |
6245 return BuildStoreNamedField(info, checked_object, value); | 6245 return BuildStoreNamedField(info, checked_object, value); |
6246 } | 6246 } |
6247 } | 6247 } |
6248 | 6248 |
6249 if (info->IsTransition()) { | 6249 if (info->IsTransition()) { |
6250 DCHECK(!info->IsLoad()); | 6250 DCHECK(!info->IsLoad()); |
6251 return BuildStoreNamedField(info, checked_object, value); | 6251 return BuildStoreNamedField(info, checked_object, value); |
6252 } | 6252 } |
6253 | 6253 |
6254 if (info->IsAccessor()) { | 6254 if (info->IsAccessorConstant()) { |
6255 Push(checked_object); | 6255 Push(checked_object); |
6256 int argument_count = 1; | 6256 int argument_count = 1; |
6257 if (!info->IsLoad()) { | 6257 if (!info->IsLoad()) { |
6258 argument_count = 2; | 6258 argument_count = 2; |
6259 Push(value); | 6259 Push(value); |
6260 } | 6260 } |
6261 | 6261 |
6262 if (NeedsWrappingFor(info->type(), info->accessor())) { | 6262 if (NeedsWrappingFor(info->type(), info->accessor())) { |
6263 HValue* function = Add<HConstant>(info->accessor()); | 6263 HValue* function = Add<HConstant>(info->accessor()); |
6264 PushArgumentsFromEnvironment(argument_count); | 6264 PushArgumentsFromEnvironment(argument_count); |
6265 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); | 6265 return New<HCallFunction>(function, argument_count, WRAP_AND_CALL); |
6266 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6266 } else if (FLAG_inline_accessors && can_inline_accessor) { |
6267 bool success = info->IsLoad() | 6267 bool success = info->IsLoad() |
6268 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6268 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
6269 : TryInlineSetter( | 6269 : TryInlineSetter( |
6270 info->accessor(), info->map(), ast_id, return_id, value); | 6270 info->accessor(), info->map(), ast_id, return_id, value); |
6271 if (success || HasStackOverflow()) return NULL; | 6271 if (success || HasStackOverflow()) return NULL; |
6272 } | 6272 } |
6273 | 6273 |
6274 PushArgumentsFromEnvironment(argument_count); | 6274 PushArgumentsFromEnvironment(argument_count); |
6275 return BuildCallConstantFunction(info->accessor(), argument_count); | 6275 return BuildCallConstantFunction(info->accessor(), argument_count); |
6276 } | 6276 } |
6277 | 6277 |
6278 DCHECK(info->IsConstant()); | 6278 DCHECK(info->IsDataConstant()); |
6279 if (info->IsLoad()) { | 6279 if (info->IsLoad()) { |
6280 return New<HConstant>(info->constant()); | 6280 return New<HConstant>(info->constant()); |
6281 } else { | 6281 } else { |
6282 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6282 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
6283 } | 6283 } |
6284 } | 6284 } |
6285 | 6285 |
6286 | 6286 |
6287 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( | 6287 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( |
6288 PropertyAccessType access_type, | 6288 PropertyAccessType access_type, |
(...skipping 1315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7604 FunctionSorter order[kMaxCallPolymorphism]; | 7604 FunctionSorter order[kMaxCallPolymorphism]; |
7605 | 7605 |
7606 bool handle_smi = false; | 7606 bool handle_smi = false; |
7607 bool handled_string = false; | 7607 bool handled_string = false; |
7608 int ordered_functions = 0; | 7608 int ordered_functions = 0; |
7609 | 7609 |
7610 int i; | 7610 int i; |
7611 for (i = 0; i < types->length() && ordered_functions < kMaxCallPolymorphism; | 7611 for (i = 0; i < types->length() && ordered_functions < kMaxCallPolymorphism; |
7612 ++i) { | 7612 ++i) { |
7613 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); | 7613 PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name); |
7614 if (info.CanAccessMonomorphic() && info.IsConstant() && | 7614 if (info.CanAccessMonomorphic() && info.IsDataConstant() && |
7615 info.constant()->IsJSFunction()) { | 7615 info.constant()->IsJSFunction()) { |
7616 if (info.type()->Is(Type::String())) { | 7616 if (info.type()->Is(Type::String())) { |
7617 if (handled_string) continue; | 7617 if (handled_string) continue; |
7618 handled_string = true; | 7618 handled_string = true; |
7619 } | 7619 } |
7620 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); | 7620 Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant()); |
7621 if (info.type()->Is(Type::Number())) { | 7621 if (info.type()->Is(Type::Number())) { |
7622 handle_smi = true; | 7622 handle_smi = true; |
7623 } | 7623 } |
7624 expr->set_target(target); | 7624 expr->set_target(target); |
(...skipping 3599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11224 HInstruction* object, | 11224 HInstruction* object, |
11225 AllocationSiteUsageContext* site_context, | 11225 AllocationSiteUsageContext* site_context, |
11226 PretenureFlag pretenure_flag) { | 11226 PretenureFlag pretenure_flag) { |
11227 Handle<Map> boilerplate_map(boilerplate_object->map()); | 11227 Handle<Map> boilerplate_map(boilerplate_object->map()); |
11228 Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors()); | 11228 Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors()); |
11229 int limit = boilerplate_map->NumberOfOwnDescriptors(); | 11229 int limit = boilerplate_map->NumberOfOwnDescriptors(); |
11230 | 11230 |
11231 int copied_fields = 0; | 11231 int copied_fields = 0; |
11232 for (int i = 0; i < limit; i++) { | 11232 for (int i = 0; i < limit; i++) { |
11233 PropertyDetails details = descriptors->GetDetails(i); | 11233 PropertyDetails details = descriptors->GetDetails(i); |
11234 if (details.type() != FIELD) continue; | 11234 if (details.type() != DATA_FIELD) continue; |
11235 copied_fields++; | 11235 copied_fields++; |
11236 FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i); | 11236 FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i); |
11237 | 11237 |
11238 | 11238 |
11239 int property_offset = field_index.offset(); | 11239 int property_offset = field_index.offset(); |
11240 Handle<Name> name(descriptors->GetKey(i)); | 11240 Handle<Name> name(descriptors->GetKey(i)); |
11241 | 11241 |
11242 // The access for the store depends on the type of the boilerplate. | 11242 // The access for the store depends on the type of the boilerplate. |
11243 HObjectAccess access = boilerplate_object->IsJSArray() ? | 11243 HObjectAccess access = boilerplate_object->IsJSArray() ? |
11244 HObjectAccess::ForJSArrayOffset(property_offset) : | 11244 HObjectAccess::ForJSArrayOffset(property_offset) : |
(...skipping 2203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13448 if (ShouldProduceTraceOutput()) { | 13448 if (ShouldProduceTraceOutput()) { |
13449 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13449 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13450 } | 13450 } |
13451 | 13451 |
13452 #ifdef DEBUG | 13452 #ifdef DEBUG |
13453 graph_->Verify(false); // No full verify. | 13453 graph_->Verify(false); // No full verify. |
13454 #endif | 13454 #endif |
13455 } | 13455 } |
13456 | 13456 |
13457 } } // namespace v8::internal | 13457 } } // namespace v8::internal |
OLD | NEW |