Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 4025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4036 } | 4036 } |
| 4037 return false; | 4037 return false; |
| 4038 } | 4038 } |
| 4039 | 4039 |
| 4040 | 4040 |
| 4041 // Determines whether the given array or object literal boilerplate satisfies | 4041 // Determines whether the given array or object literal boilerplate satisfies |
| 4042 // all limits to be considered for fast deep-copying and computes the total | 4042 // all limits to be considered for fast deep-copying and computes the total |
| 4043 // size of all objects that are part of the graph. | 4043 // size of all objects that are part of the graph. |
| 4044 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 4044 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
| 4045 int max_depth, | 4045 int max_depth, |
| 4046 int* max_properties, | 4046 int* max_properties) { |
| 4047 int* data_size, | |
| 4048 int* pointer_size) { | |
| 4049 if (boilerplate->map()->is_deprecated()) { | 4047 if (boilerplate->map()->is_deprecated()) { |
| 4050 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); | 4048 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); |
| 4051 if (result->IsSmi()) return false; | 4049 if (result->IsSmi()) return false; |
| 4052 } | 4050 } |
| 4053 | 4051 |
| 4054 ASSERT(max_depth >= 0 && *max_properties >= 0); | 4052 ASSERT(max_depth >= 0 && *max_properties >= 0); |
| 4055 if (max_depth == 0) return false; | 4053 if (max_depth == 0) return false; |
| 4056 | 4054 |
| 4057 Isolate* isolate = boilerplate->GetIsolate(); | 4055 Isolate* isolate = boilerplate->GetIsolate(); |
| 4058 Handle<FixedArrayBase> elements(boilerplate->elements()); | 4056 Handle<FixedArrayBase> elements(boilerplate->elements()); |
| 4059 if (elements->length() > 0 && | 4057 if (elements->length() > 0 && |
| 4060 elements->map() != isolate->heap()->fixed_cow_array_map()) { | 4058 elements->map() != isolate->heap()->fixed_cow_array_map()) { |
| 4061 if (boilerplate->HasFastDoubleElements()) { | 4059 if (boilerplate->HasFastObjectElements()) { |
| 4062 *data_size += FixedDoubleArray::SizeFor(elements->length()); | |
| 4063 } else if (boilerplate->HasFastObjectElements()) { | |
| 4064 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 4060 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 4065 int length = elements->length(); | 4061 int length = elements->length(); |
| 4066 for (int i = 0; i < length; i++) { | 4062 for (int i = 0; i < length; i++) { |
| 4067 if ((*max_properties)-- == 0) return false; | 4063 if ((*max_properties)-- == 0) return false; |
| 4068 Handle<Object> value(fast_elements->get(i), isolate); | 4064 Handle<Object> value(fast_elements->get(i), isolate); |
| 4069 if (value->IsJSObject()) { | 4065 if (value->IsJSObject()) { |
| 4070 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 4066 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 4071 if (!IsFastLiteral(value_object, | 4067 if (!IsFastLiteral(value_object, |
| 4072 max_depth - 1, | 4068 max_depth - 1, |
| 4073 max_properties, | 4069 max_properties)) { |
| 4074 data_size, | |
| 4075 pointer_size)) { | |
| 4076 return false; | 4070 return false; |
| 4077 } | 4071 } |
| 4078 } | 4072 } |
| 4079 } | 4073 } |
| 4080 *pointer_size += FixedArray::SizeFor(length); | |
| 4081 } else { | 4074 } else { |
| 4082 return false; | 4075 return false; |
| 4083 } | 4076 } |
| 4084 } | 4077 } |
| 4085 | 4078 |
| 4086 Handle<FixedArray> properties(boilerplate->properties()); | 4079 Handle<FixedArray> properties(boilerplate->properties()); |
| 4087 if (properties->length() > 0) { | 4080 if (properties->length() > 0) { |
| 4088 return false; | 4081 return false; |
| 4089 } else { | 4082 } else { |
| 4090 Handle<DescriptorArray> descriptors( | 4083 Handle<DescriptorArray> descriptors( |
| 4091 boilerplate->map()->instance_descriptors()); | 4084 boilerplate->map()->instance_descriptors()); |
| 4092 int limit = boilerplate->map()->NumberOfOwnDescriptors(); | 4085 int limit = boilerplate->map()->NumberOfOwnDescriptors(); |
| 4093 for (int i = 0; i < limit; i++) { | 4086 for (int i = 0; i < limit; i++) { |
| 4094 PropertyDetails details = descriptors->GetDetails(i); | 4087 PropertyDetails details = descriptors->GetDetails(i); |
| 4095 if (details.type() != FIELD) continue; | 4088 if (details.type() != FIELD) continue; |
| 4096 Representation representation = details.representation(); | |
| 4097 int index = descriptors->GetFieldIndex(i); | 4089 int index = descriptors->GetFieldIndex(i); |
| 4098 if ((*max_properties)-- == 0) return false; | 4090 if ((*max_properties)-- == 0) return false; |
| 4099 Handle<Object> value(boilerplate->InObjectPropertyAt(index), isolate); | 4091 Handle<Object> value(boilerplate->InObjectPropertyAt(index), isolate); |
| 4100 if (value->IsJSObject()) { | 4092 if (value->IsJSObject()) { |
| 4101 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 4093 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 4102 if (!IsFastLiteral(value_object, | 4094 if (!IsFastLiteral(value_object, |
| 4103 max_depth - 1, | 4095 max_depth - 1, |
| 4104 max_properties, | 4096 max_properties)) { |
| 4105 data_size, | |
| 4106 pointer_size)) { | |
| 4107 return false; | 4097 return false; |
| 4108 } | 4098 } |
| 4109 } else if (representation.IsDouble()) { | |
| 4110 *data_size += HeapNumber::kSize; | |
| 4111 } | 4099 } |
| 4112 } | 4100 } |
| 4113 } | 4101 } |
| 4114 | |
| 4115 *pointer_size += boilerplate->map()->instance_size(); | |
| 4116 return true; | 4102 return true; |
| 4117 } | 4103 } |
| 4118 | 4104 |
| 4119 | 4105 |
| 4120 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 4106 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 4121 ASSERT(!HasStackOverflow()); | 4107 ASSERT(!HasStackOverflow()); |
| 4122 ASSERT(current_block() != NULL); | 4108 ASSERT(current_block() != NULL); |
| 4123 ASSERT(current_block()->HasPredecessor()); | 4109 ASSERT(current_block()->HasPredecessor()); |
| 4124 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4110 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 4125 HValue* context = environment()->context(); | |
| 4126 HInstruction* literal; | 4111 HInstruction* literal; |
| 4127 | 4112 |
| 4128 // Check whether to use fast or slow deep-copying for boilerplate. | 4113 // Check whether to use fast or slow deep-copying for boilerplate. |
| 4129 int data_size = 0; | |
| 4130 int pointer_size = 0; | |
| 4131 int max_properties = kMaxFastLiteralProperties; | 4114 int max_properties = kMaxFastLiteralProperties; |
| 4132 Handle<Object> original_boilerplate(closure->literals()->get( | 4115 Handle<Object> original_boilerplate(closure->literals()->get( |
| 4133 expr->literal_index()), isolate()); | 4116 expr->literal_index()), isolate()); |
| 4134 if (original_boilerplate->IsJSObject() && | 4117 if (original_boilerplate->IsJSObject() && |
| 4135 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), | 4118 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), |
| 4136 kMaxFastLiteralDepth, | 4119 kMaxFastLiteralDepth, |
| 4137 &max_properties, | 4120 &max_properties)) { |
| 4138 &data_size, | |
| 4139 &pointer_size)) { | |
| 4140 Handle<JSObject> original_boilerplate_object = | 4121 Handle<JSObject> original_boilerplate_object = |
| 4141 Handle<JSObject>::cast(original_boilerplate); | 4122 Handle<JSObject>::cast(original_boilerplate); |
| 4142 Handle<JSObject> boilerplate_object = | 4123 Handle<JSObject> boilerplate_object = |
| 4143 DeepCopy(original_boilerplate_object); | 4124 DeepCopy(original_boilerplate_object); |
| 4144 | 4125 |
| 4145 literal = BuildFastLiteral(context, | 4126 literal = BuildFastLiteral(boilerplate_object, |
| 4146 boilerplate_object, | |
| 4147 original_boilerplate_object, | 4127 original_boilerplate_object, |
| 4148 Handle<Object>::null(), | 4128 Handle<Object>::null(), |
| 4149 data_size, | |
| 4150 pointer_size, | |
| 4151 DONT_TRACK_ALLOCATION_SITE); | 4129 DONT_TRACK_ALLOCATION_SITE); |
| 4152 } else { | 4130 } else { |
| 4153 NoObservableSideEffectsScope no_effects(this); | 4131 NoObservableSideEffectsScope no_effects(this); |
| 4154 Handle<FixedArray> closure_literals(closure->literals(), isolate()); | 4132 Handle<FixedArray> closure_literals(closure->literals(), isolate()); |
| 4155 Handle<FixedArray> constant_properties = expr->constant_properties(); | 4133 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 4156 int literal_index = expr->literal_index(); | 4134 int literal_index = expr->literal_index(); |
| 4157 int flags = expr->fast_elements() | 4135 int flags = expr->fast_elements() |
| 4158 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; | 4136 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; |
| 4159 flags |= expr->has_function() | 4137 flags |= expr->has_function() |
| 4160 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; | 4138 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4242 } | 4220 } |
| 4243 } | 4221 } |
| 4244 | 4222 |
| 4245 | 4223 |
| 4246 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 4224 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 4247 ASSERT(!HasStackOverflow()); | 4225 ASSERT(!HasStackOverflow()); |
| 4248 ASSERT(current_block() != NULL); | 4226 ASSERT(current_block() != NULL); |
| 4249 ASSERT(current_block()->HasPredecessor()); | 4227 ASSERT(current_block()->HasPredecessor()); |
| 4250 ZoneList<Expression*>* subexprs = expr->values(); | 4228 ZoneList<Expression*>* subexprs = expr->values(); |
| 4251 int length = subexprs->length(); | 4229 int length = subexprs->length(); |
| 4252 HValue* context = environment()->context(); | |
| 4253 HInstruction* literal; | 4230 HInstruction* literal; |
| 4254 | 4231 |
| 4255 Handle<AllocationSite> site; | 4232 Handle<AllocationSite> site; |
| 4256 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 4233 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
| 4257 bool uninitialized = false; | 4234 bool uninitialized = false; |
| 4258 Handle<Object> literals_cell(literals->get(expr->literal_index()), | 4235 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
| 4259 isolate()); | 4236 isolate()); |
| 4260 Handle<Object> raw_boilerplate; | 4237 Handle<Object> raw_boilerplate; |
| 4261 if (literals_cell->IsUndefined()) { | 4238 if (literals_cell->IsUndefined()) { |
| 4262 uninitialized = true; | 4239 uninitialized = true; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 4288 ElementsKind boilerplate_elements_kind = | 4265 ElementsKind boilerplate_elements_kind = |
| 4289 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); | 4266 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); |
| 4290 | 4267 |
| 4291 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 4268 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
| 4292 // end, we want to quit creating allocation site info after a certain number | 4269 // end, we want to quit creating allocation site info after a certain number |
| 4293 // of GCs for a call site. | 4270 // of GCs for a call site. |
| 4294 AllocationSiteMode mode = AllocationSite::GetMode( | 4271 AllocationSiteMode mode = AllocationSite::GetMode( |
| 4295 boilerplate_elements_kind); | 4272 boilerplate_elements_kind); |
| 4296 | 4273 |
| 4297 // Check whether to use fast or slow deep-copying for boilerplate. | 4274 // Check whether to use fast or slow deep-copying for boilerplate. |
| 4298 int data_size = 0; | |
| 4299 int pointer_size = 0; | |
| 4300 int max_properties = kMaxFastLiteralProperties; | 4275 int max_properties = kMaxFastLiteralProperties; |
| 4301 HCheckMaps* type_check = NULL; | 4276 HCheckMaps* type_check = NULL; |
| 4302 if (IsFastLiteral(original_boilerplate_object, | 4277 if (IsFastLiteral(original_boilerplate_object, |
| 4303 kMaxFastLiteralDepth, | 4278 kMaxFastLiteralDepth, |
| 4304 &max_properties, | 4279 &max_properties)) { |
| 4305 &data_size, | |
| 4306 &pointer_size)) { | |
| 4307 if (mode == TRACK_ALLOCATION_SITE) { | |
| 4308 pointer_size += AllocationMemento::kSize; | |
| 4309 } | |
| 4310 | |
| 4311 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); | 4280 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); |
| 4312 literal = BuildFastLiteral(context, | 4281 literal = BuildFastLiteral(boilerplate_object, |
| 4313 boilerplate_object, | |
| 4314 original_boilerplate_object, | 4282 original_boilerplate_object, |
| 4315 site, | 4283 site, |
| 4316 data_size, | |
| 4317 pointer_size, | |
| 4318 mode); | 4284 mode); |
| 4319 } else { | 4285 } else { |
| 4320 NoObservableSideEffectsScope no_effects(this); | 4286 NoObservableSideEffectsScope no_effects(this); |
| 4321 // Boilerplate already exists and constant elements are never accessed, | 4287 // Boilerplate already exists and constant elements are never accessed, |
| 4322 // pass an empty fixed array to the runtime function instead. | 4288 // pass an empty fixed array to the runtime function instead. |
| 4323 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 4289 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
| 4324 int literal_index = expr->literal_index(); | 4290 int literal_index = expr->literal_index(); |
| 4325 | 4291 |
| 4326 Add<HPushArgument>(Add<HConstant>(literals)); | 4292 Add<HPushArgument>(Add<HConstant>(literals)); |
| 4327 Add<HPushArgument>(Add<HConstant>(literal_index)); | 4293 Add<HPushArgument>(Add<HConstant>(literal_index)); |
| (...skipping 3884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8212 if (function_state()->outer() != NULL) { | 8178 if (function_state()->outer() != NULL) { |
| 8213 return New<HConstant>( | 8179 return New<HConstant>( |
| 8214 function_state()->compilation_info()->closure()); | 8180 function_state()->compilation_info()->closure()); |
| 8215 } else { | 8181 } else { |
| 8216 return new(zone()) HThisFunction; | 8182 return new(zone()) HThisFunction; |
| 8217 } | 8183 } |
| 8218 } | 8184 } |
| 8219 | 8185 |
| 8220 | 8186 |
| 8221 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 8187 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| 8222 HValue* context, | |
| 8223 Handle<JSObject> boilerplate_object, | |
| 8224 Handle<JSObject> original_boilerplate_object, | |
| 8225 Handle<Object> allocation_site, | |
| 8226 int data_size, | |
| 8227 int pointer_size, | |
| 8228 AllocationSiteMode mode) { | |
| 8229 NoObservableSideEffectsScope no_effects(this); | |
| 8230 | |
| 8231 HInstruction* target = NULL; | |
| 8232 HInstruction* data_target = NULL; | |
| 8233 | |
| 8234 if (isolate()->heap()->GetPretenureMode() == TENURED) { | |
| 8235 if (data_size != 0) { | |
| 8236 HValue* size_in_bytes = Add<HConstant>(data_size); | |
| 8237 data_target = Add<HAllocate>(size_in_bytes, HType::JSObject(), TENURED, | |
| 8238 FIXED_DOUBLE_ARRAY_TYPE); | |
| 8239 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); | |
| 8240 AddStoreMapConstant(data_target, free_space_map); | |
| 8241 HObjectAccess access = | |
| 8242 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); | |
| 8243 Add<HStoreNamedField>(data_target, access, size_in_bytes); | |
| 8244 } | |
| 8245 if (pointer_size != 0) { | |
| 8246 HValue* size_in_bytes = Add<HConstant>(pointer_size); | |
| 8247 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), TENURED, | |
| 8248 JS_OBJECT_TYPE); | |
| 8249 } | |
| 8250 } else { | |
| 8251 InstanceType instance_type = boilerplate_object->map()->instance_type(); | |
| 8252 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); | |
| 8253 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), NOT_TENURED, | |
| 8254 instance_type); | |
| 8255 } | |
| 8256 | |
| 8257 int offset = 0; | |
| 8258 int data_offset = 0; | |
| 8259 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, | |
| 8260 allocation_site, target, &offset, data_target, | |
| 8261 &data_offset, mode); | |
| 8262 return target; | |
| 8263 } | |
| 8264 | |
| 8265 | |
| 8266 void HOptimizedGraphBuilder::BuildEmitDeepCopy( | |
| 8267 Handle<JSObject> boilerplate_object, | 8188 Handle<JSObject> boilerplate_object, |
| 8268 Handle<JSObject> original_boilerplate_object, | 8189 Handle<JSObject> original_boilerplate_object, |
|
Michael Starzinger
2013/08/16 20:18:56
Why does this function take the deep-copied boiler
Hannes Payer (out of office)
2013/08/22 13:27:23
Thanks for the comment, removed. Done.
| |
| 8269 Handle<Object> allocation_site_object, | 8190 Handle<Object> allocation_site_object, |
| 8270 HInstruction* target, | |
| 8271 int* offset, | |
| 8272 HInstruction* data_target, | |
| 8273 int* data_offset, | |
| 8274 AllocationSiteMode mode) { | 8191 AllocationSiteMode mode) { |
| 8192 NoObservableSideEffectsScope no_effects(this); | |
| 8275 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && | 8193 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && |
| 8276 boilerplate_object->map()->CanTrackAllocationSite(); | 8194 boilerplate_object->map()->CanTrackAllocationSite(); |
| 8277 | 8195 |
| 8278 // If using allocation sites, then the payload on the site should already | 8196 // If using allocation sites, then the payload on the site should already |
| 8279 // be filled in as a valid (boilerplate) array. | 8197 // be filled in as a valid (boilerplate) array. |
| 8280 ASSERT(!create_allocation_site_info || | 8198 ASSERT(!create_allocation_site_info || |
| 8281 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); | 8199 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); |
| 8282 | 8200 |
| 8283 HInstruction* allocation_site = NULL; | |
| 8284 | |
| 8285 if (create_allocation_site_info) { | |
| 8286 allocation_site = Add<HConstant>(allocation_site_object); | |
| 8287 } | |
| 8288 | |
| 8289 // Only elements backing stores for non-COW arrays need to be copied. | |
| 8290 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 8201 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 8291 Handle<FixedArrayBase> original_elements( | 8202 Handle<FixedArrayBase> original_elements( |
| 8292 original_boilerplate_object->elements()); | 8203 original_boilerplate_object->elements()); |
| 8293 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 8204 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
| 8294 | 8205 |
| 8295 int object_offset = *offset; | |
| 8296 int object_size = boilerplate_object->map()->instance_size(); | 8206 int object_size = boilerplate_object->map()->instance_size(); |
| 8207 int object_offset = object_size; | |
| 8208 | |
| 8209 if (create_allocation_site_info) { | |
| 8210 object_size += AllocationMemento::kSize; | |
| 8211 } | |
| 8212 | |
| 8213 HValue* object_size_constant = Add<HConstant>(object_size); | |
| 8214 HInstruction* object = Add<HAllocate>(object_size_constant, HType::JSObject(), | |
| 8215 isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE); | |
| 8216 | |
| 8217 if (create_allocation_site_info) { | |
| 8218 HInstruction* allocation_site = Add<HConstant>(allocation_site_object); | |
| 8219 BuildCreateAllocationMemento(object, object_offset, allocation_site); | |
| 8220 } | |
| 8221 | |
| 8297 int elements_size = (elements->length() > 0 && | 8222 int elements_size = (elements->length() > 0 && |
| 8298 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 8223 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
| 8299 elements->Size() : 0; | 8224 elements->Size() : 0; |
| 8300 int elements_offset = 0; | 8225 HInstruction* object_elements = NULL; |
| 8301 | 8226 if (elements_size > 0) { |
| 8302 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { | 8227 HValue* object_elements_size = Add<HConstant>(elements_size); |
| 8303 elements_offset = *data_offset; | 8228 if (boilerplate_object->HasFastDoubleElements()) { |
| 8304 *data_offset += elements_size; | 8229 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), |
| 8305 } else { | 8230 isolate()->heap()->GetPretenureMode(), FIXED_DOUBLE_ARRAY_TYPE); |
| 8306 // Place elements right after this object. | 8231 } else { |
| 8307 elements_offset = *offset + object_size; | 8232 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), |
| 8308 *offset += elements_size; | 8233 isolate()->heap()->GetPretenureMode(), FIXED_ARRAY_TYPE); |
| 8234 } | |
| 8309 } | 8235 } |
| 8310 // Increase the offset so that subsequent objects end up right after this | |
| 8311 // object (and it's elements if they are allocated in the same space). | |
| 8312 *offset += object_size; | |
| 8313 | 8236 |
| 8314 // Copy object elements if non-COW. | 8237 // Copy object elements if non-COW. |
| 8315 HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target, | 8238 BuildEmitObjectHeader(boilerplate_object, object, object_elements); |
| 8316 data_target, object_offset, elements_offset, elements_size); | |
| 8317 if (object_elements != NULL) { | 8239 if (object_elements != NULL) { |
| 8318 BuildEmitElements(elements, original_elements, kind, object_elements, | 8240 BuildEmitElements(elements, original_elements, kind, object_elements); |
| 8319 target, offset, data_target, data_offset); | |
| 8320 } | 8241 } |
| 8321 | 8242 |
| 8322 // Copy in-object properties. | 8243 // Copy in-object properties. |
| 8323 if (boilerplate_object->map()->NumberOfFields() != 0) { | 8244 if (boilerplate_object->map()->NumberOfFields() != 0) { |
| 8324 HValue* object_properties = | |
| 8325 Add<HInnerAllocatedObject>(target, object_offset); | |
| 8326 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, | 8245 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, |
| 8327 object_properties, target, offset, data_target, data_offset); | 8246 object); |
| 8328 } | 8247 } |
| 8329 | 8248 return object; |
| 8330 // Create allocation site info. | |
| 8331 if (mode == TRACK_ALLOCATION_SITE && | |
| 8332 boilerplate_object->map()->CanTrackAllocationSite()) { | |
| 8333 elements_offset += AllocationMemento::kSize; | |
| 8334 *offset += AllocationMemento::kSize; | |
| 8335 BuildCreateAllocationMemento(target, JSArray::kSize, allocation_site); | |
| 8336 } | |
| 8337 } | 8249 } |
| 8338 | 8250 |
| 8339 | 8251 |
| 8340 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( | 8252 void HOptimizedGraphBuilder::BuildEmitObjectHeader( |
| 8341 Handle<JSObject> boilerplate_object, | 8253 Handle<JSObject> boilerplate_object, |
| 8342 HInstruction* target, | 8254 HInstruction* object, |
| 8343 HInstruction* data_target, | 8255 HInstruction* object_elements) { |
| 8344 int object_offset, | |
| 8345 int elements_offset, | |
| 8346 int elements_size) { | |
| 8347 ASSERT(boilerplate_object->properties()->length() == 0); | 8256 ASSERT(boilerplate_object->properties()->length() == 0); |
| 8348 HValue* result = NULL; | |
| 8349 | 8257 |
| 8350 HValue* object_header = Add<HInnerAllocatedObject>(target, object_offset); | |
| 8351 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 8258 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
| 8352 AddStoreMapConstant(object_header, boilerplate_object_map); | 8259 AddStoreMapConstant(object, boilerplate_object_map); |
| 8353 | 8260 |
| 8354 HInstruction* elements; | 8261 if (object_elements == NULL) { |
| 8355 if (elements_size == 0) { | |
| 8356 Handle<Object> elements_field = | 8262 Handle<Object> elements_field = |
| 8357 Handle<Object>(boilerplate_object->elements(), isolate()); | 8263 Handle<Object>(boilerplate_object->elements(), isolate()); |
| 8358 elements = Add<HConstant>(elements_field); | 8264 object_elements = Add<HConstant>(elements_field); |
| 8359 } else { | |
| 8360 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { | |
| 8361 elements = Add<HInnerAllocatedObject>(data_target, elements_offset); | |
| 8362 } else { | |
| 8363 elements = Add<HInnerAllocatedObject>(target, elements_offset); | |
| 8364 } | |
| 8365 result = elements; | |
| 8366 } | 8265 } |
| 8367 Add<HStoreNamedField>(object_header, HObjectAccess::ForElementsPointer(), | 8266 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 8368 elements); | 8267 object_elements); |
| 8369 | 8268 |
| 8370 Handle<Object> properties_field = | 8269 Handle<Object> properties_field = |
| 8371 Handle<Object>(boilerplate_object->properties(), isolate()); | 8270 Handle<Object>(boilerplate_object->properties(), isolate()); |
| 8372 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 8271 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
| 8373 HInstruction* properties = Add<HConstant>(properties_field); | 8272 HInstruction* properties = Add<HConstant>(properties_field); |
| 8374 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 8273 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| 8375 Add<HStoreNamedField>(object_header, access, properties); | 8274 Add<HStoreNamedField>(object, access, properties); |
| 8376 | 8275 |
| 8377 if (boilerplate_object->IsJSArray()) { | 8276 if (boilerplate_object->IsJSArray()) { |
| 8378 Handle<JSArray> boilerplate_array = | 8277 Handle<JSArray> boilerplate_array = |
| 8379 Handle<JSArray>::cast(boilerplate_object); | 8278 Handle<JSArray>::cast(boilerplate_object); |
| 8380 Handle<Object> length_field = | 8279 Handle<Object> length_field = |
| 8381 Handle<Object>(boilerplate_array->length(), isolate()); | 8280 Handle<Object>(boilerplate_array->length(), isolate()); |
| 8382 HInstruction* length = Add<HConstant>(length_field); | 8281 HInstruction* length = Add<HConstant>(length_field); |
| 8383 | 8282 |
| 8384 ASSERT(boilerplate_array->length()->IsSmi()); | 8283 ASSERT(boilerplate_array->length()->IsSmi()); |
| 8385 Add<HStoreNamedField>(object_header, HObjectAccess::ForArrayLength( | 8284 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength( |
| 8386 boilerplate_array->GetElementsKind()), length); | 8285 boilerplate_array->GetElementsKind()), length); |
| 8387 } | 8286 } |
| 8388 | |
| 8389 return result; | |
| 8390 } | 8287 } |
| 8391 | 8288 |
| 8392 | 8289 |
| 8393 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 8290 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| 8394 Handle<JSObject> boilerplate_object, | 8291 Handle<JSObject> boilerplate_object, |
| 8395 Handle<JSObject> original_boilerplate_object, | 8292 Handle<JSObject> original_boilerplate_object, |
|
Michael Starzinger
2013/08/16 20:18:56
Likewise.
Hannes Payer (out of office)
2013/08/22 13:27:23
Done.
| |
| 8396 HValue* object_properties, | 8293 HInstruction* object) { |
| 8397 HInstruction* target, | |
| 8398 int* offset, | |
| 8399 HInstruction* data_target, | |
| 8400 int* data_offset) { | |
| 8401 Handle<DescriptorArray> descriptors( | 8294 Handle<DescriptorArray> descriptors( |
| 8402 boilerplate_object->map()->instance_descriptors()); | 8295 boilerplate_object->map()->instance_descriptors()); |
| 8403 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); | 8296 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); |
| 8404 | 8297 |
| 8405 int copied_fields = 0; | 8298 int copied_fields = 0; |
| 8406 for (int i = 0; i < limit; i++) { | 8299 for (int i = 0; i < limit; i++) { |
| 8407 PropertyDetails details = descriptors->GetDetails(i); | 8300 PropertyDetails details = descriptors->GetDetails(i); |
| 8408 if (details.type() != FIELD) continue; | 8301 if (details.type() != FIELD) continue; |
| 8409 copied_fields++; | 8302 copied_fields++; |
| 8410 int index = descriptors->GetFieldIndex(i); | 8303 int index = descriptors->GetFieldIndex(i); |
| 8411 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); | 8304 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); |
| 8412 Handle<Name> name(descriptors->GetKey(i)); | 8305 Handle<Name> name(descriptors->GetKey(i)); |
| 8413 Handle<Object> value = | 8306 Handle<Object> value = |
| 8414 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), | 8307 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), |
| 8415 isolate()); | 8308 isolate()); |
| 8416 | 8309 |
| 8417 // The access for the store depends on the type of the boilerplate. | 8310 // The access for the store depends on the type of the boilerplate. |
| 8418 HObjectAccess access = boilerplate_object->IsJSArray() ? | 8311 HObjectAccess access = boilerplate_object->IsJSArray() ? |
| 8419 HObjectAccess::ForJSArrayOffset(property_offset) : | 8312 HObjectAccess::ForJSArrayOffset(property_offset) : |
| 8420 HObjectAccess::ForJSObjectOffset(property_offset); | 8313 HObjectAccess::ForJSObjectOffset(property_offset); |
| 8421 | 8314 |
| 8422 if (value->IsJSObject()) { | 8315 if (value->IsJSObject()) { |
| 8423 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 8316 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 8424 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 8317 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| 8425 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), | 8318 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), |
| 8426 isolate())); | 8319 isolate())); |
| 8427 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, | 8320 HInstruction* result = |
| 8428 *offset); | 8321 BuildFastLiteral(value_object, original_value_object, |
| 8429 | 8322 Handle<Object>::null(), DONT_TRACK_ALLOCATION_SITE); |
| 8430 Add<HStoreNamedField>(object_properties, access, value_instruction); | 8323 Add<HStoreNamedField>(object, access, result); |
| 8431 BuildEmitDeepCopy(value_object, original_value_object, | |
| 8432 Handle<Object>::null(), target, | |
| 8433 offset, data_target, data_offset, | |
| 8434 DONT_TRACK_ALLOCATION_SITE); | |
| 8435 } else { | 8324 } else { |
| 8436 Representation representation = details.representation(); | 8325 Representation representation = details.representation(); |
| 8437 HInstruction* value_instruction = Add<HConstant>(value); | 8326 HInstruction* value_instruction = Add<HConstant>(value); |
| 8438 | 8327 |
| 8439 if (representation.IsDouble()) { | 8328 if (representation.IsDouble()) { |
| 8440 // Allocate a HeapNumber box and store the value into it. | 8329 // Allocate a HeapNumber box and store the value into it. |
| 8441 HInstruction* double_box; | 8330 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); |
| 8442 if (data_target != NULL) { | 8331 HInstruction* double_box = |
| 8443 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); | 8332 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), |
| 8444 *data_offset += HeapNumber::kSize; | 8333 isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE); |
| 8445 } else { | |
| 8446 double_box = Add<HInnerAllocatedObject>(target, *offset); | |
| 8447 *offset += HeapNumber::kSize; | |
| 8448 } | |
| 8449 AddStoreMapConstant(double_box, | 8334 AddStoreMapConstant(double_box, |
| 8450 isolate()->factory()->heap_number_map()); | 8335 isolate()->factory()->heap_number_map()); |
| 8451 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), | 8336 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), |
| 8452 value_instruction); | 8337 value_instruction); |
| 8453 value_instruction = double_box; | 8338 value_instruction = double_box; |
| 8454 } | 8339 } |
| 8455 | 8340 |
| 8456 Add<HStoreNamedField>(object_properties, access, value_instruction); | 8341 Add<HStoreNamedField>(object, access, value_instruction); |
| 8457 } | 8342 } |
| 8458 } | 8343 } |
| 8459 | 8344 |
| 8460 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 8345 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
| 8461 HInstruction* value_instruction = | 8346 HInstruction* value_instruction = |
| 8462 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 8347 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
| 8463 for (int i = copied_fields; i < inobject_properties; i++) { | 8348 for (int i = copied_fields; i < inobject_properties; i++) { |
| 8464 ASSERT(boilerplate_object->IsJSObject()); | 8349 ASSERT(boilerplate_object->IsJSObject()); |
| 8465 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 8350 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
| 8466 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 8351 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
| 8467 Add<HStoreNamedField>(object_properties, access, value_instruction); | 8352 Add<HStoreNamedField>(object, access, value_instruction); |
| 8468 } | 8353 } |
| 8469 } | 8354 } |
| 8470 | 8355 |
| 8471 | 8356 |
| 8472 void HOptimizedGraphBuilder::BuildEmitElements( | 8357 void HOptimizedGraphBuilder::BuildEmitElements( |
| 8473 Handle<FixedArrayBase> elements, | 8358 Handle<FixedArrayBase> elements, |
| 8474 Handle<FixedArrayBase> original_elements, | 8359 Handle<FixedArrayBase> original_elements, |
|
Michael Starzinger
2013/08/16 20:18:56
Likewise.
Hannes Payer (out of office)
2013/08/22 13:27:23
Done.
| |
| 8475 ElementsKind kind, | 8360 ElementsKind kind, |
| 8476 HValue* object_elements, | 8361 HValue* object_elements) { |
| 8477 HInstruction* target, | |
| 8478 int* offset, | |
| 8479 HInstruction* data_target, | |
| 8480 int* data_offset) { | |
| 8481 int elements_length = elements->length(); | 8362 int elements_length = elements->length(); |
| 8482 HValue* object_elements_length = Add<HConstant>(elements_length); | 8363 HValue* object_elements_length = Add<HConstant>(elements_length); |
| 8483 | |
| 8484 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); | 8364 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); |
| 8485 | 8365 |
| 8486 // Copy elements backing store content. | 8366 // Copy elements backing store content. |
| 8487 if (elements->IsFixedDoubleArray()) { | 8367 if (elements->IsFixedDoubleArray()) { |
| 8488 BuildEmitFixedDoubleArray(elements, kind, object_elements); | 8368 BuildEmitFixedDoubleArray(elements, kind, object_elements); |
| 8489 } else if (elements->IsFixedArray()) { | 8369 } else if (elements->IsFixedArray()) { |
| 8490 BuildEmitFixedArray(elements, original_elements, kind, object_elements, | 8370 BuildEmitFixedArray(elements, original_elements, kind, object_elements); |
| 8491 target, offset, data_target, data_offset); | |
| 8492 } else { | 8371 } else { |
| 8493 UNREACHABLE(); | 8372 UNREACHABLE(); |
| 8494 } | 8373 } |
| 8495 } | 8374 } |
| 8496 | 8375 |
| 8497 | 8376 |
| 8498 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( | 8377 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( |
| 8499 Handle<FixedArrayBase> elements, | 8378 Handle<FixedArrayBase> elements, |
| 8500 ElementsKind kind, | 8379 ElementsKind kind, |
| 8501 HValue* object_elements) { | 8380 HValue* object_elements) { |
| 8502 HInstruction* boilerplate_elements = Add<HConstant>(elements); | 8381 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| 8503 int elements_length = elements->length(); | 8382 int elements_length = elements->length(); |
| 8504 for (int i = 0; i < elements_length; i++) { | 8383 for (int i = 0; i < elements_length; i++) { |
| 8505 HValue* key_constant = Add<HConstant>(i); | 8384 HValue* key_constant = Add<HConstant>(i); |
| 8506 HInstruction* value_instruction = | 8385 HInstruction* value_instruction = |
| 8507 Add<HLoadKeyed>(boilerplate_elements, key_constant, | 8386 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 8508 static_cast<HValue*>(NULL), kind, | 8387 static_cast<HValue*>(NULL), kind, |
| 8509 ALLOW_RETURN_HOLE); | 8388 ALLOW_RETURN_HOLE); |
| 8510 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant, | 8389 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant, |
| 8511 value_instruction, kind); | 8390 value_instruction, kind); |
| 8512 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 8391 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 8513 } | 8392 } |
| 8514 } | 8393 } |
| 8515 | 8394 |
| 8516 | 8395 |
| 8517 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 8396 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| 8518 Handle<FixedArrayBase> elements, | 8397 Handle<FixedArrayBase> elements, |
| 8519 Handle<FixedArrayBase> original_elements, | 8398 Handle<FixedArrayBase> original_elements, |
|
Michael Starzinger
2013/08/16 20:18:56
Likewise.
Hannes Payer (out of office)
2013/08/22 13:27:23
Done.
| |
| 8520 ElementsKind kind, | 8399 ElementsKind kind, |
| 8521 HValue* object_elements, | 8400 HValue* object_elements) { |
| 8522 HInstruction* target, | |
| 8523 int* offset, | |
| 8524 HInstruction* data_target, | |
| 8525 int* data_offset) { | |
| 8526 HInstruction* boilerplate_elements = Add<HConstant>(elements); | 8401 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
| 8527 int elements_length = elements->length(); | 8402 int elements_length = elements->length(); |
| 8528 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 8403 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 8529 Handle<FixedArray> original_fast_elements = | 8404 Handle<FixedArray> original_fast_elements = |
| 8530 Handle<FixedArray>::cast(original_elements); | 8405 Handle<FixedArray>::cast(original_elements); |
| 8531 for (int i = 0; i < elements_length; i++) { | 8406 for (int i = 0; i < elements_length; i++) { |
| 8532 Handle<Object> value(fast_elements->get(i), isolate()); | 8407 Handle<Object> value(fast_elements->get(i), isolate()); |
| 8533 HValue* key_constant = Add<HConstant>(i); | 8408 HValue* key_constant = Add<HConstant>(i); |
| 8534 if (value->IsJSObject()) { | 8409 if (value->IsJSObject()) { |
| 8535 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 8410 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 8536 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 8411 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| 8537 Handle<Object>(original_fast_elements->get(i), isolate())); | 8412 Handle<Object>(original_fast_elements->get(i), isolate())); |
| 8538 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, | 8413 HInstruction* result = |
| 8539 *offset); | 8414 BuildFastLiteral(value_object, original_value_object, |
| 8540 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); | 8415 Handle<Object>::null(), DONT_TRACK_ALLOCATION_SITE); |
| 8541 BuildEmitDeepCopy(value_object, original_value_object, | 8416 Add<HStoreKeyed>(object_elements, key_constant, result, kind); |
| 8542 Handle<Object>::null(), target, | |
| 8543 offset, data_target, data_offset, | |
| 8544 DONT_TRACK_ALLOCATION_SITE); | |
| 8545 } else { | 8417 } else { |
| 8546 HInstruction* value_instruction = | 8418 HInstruction* value_instruction = |
| 8547 Add<HLoadKeyed>(boilerplate_elements, key_constant, | 8419 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
| 8548 static_cast<HValue*>(NULL), kind, | 8420 static_cast<HValue*>(NULL), kind, |
| 8549 ALLOW_RETURN_HOLE); | 8421 ALLOW_RETURN_HOLE); |
| 8550 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); | 8422 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); |
| 8551 } | 8423 } |
| 8552 } | 8424 } |
| 8553 } | 8425 } |
| 8554 | 8426 |
| (...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9829 if (ShouldProduceTraceOutput()) { | 9701 if (ShouldProduceTraceOutput()) { |
| 9830 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9702 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9831 } | 9703 } |
| 9832 | 9704 |
| 9833 #ifdef DEBUG | 9705 #ifdef DEBUG |
| 9834 graph_->Verify(false); // No full verify. | 9706 graph_->Verify(false); // No full verify. |
| 9835 #endif | 9707 #endif |
| 9836 } | 9708 } |
| 9837 | 9709 |
| 9838 } } // namespace v8::internal | 9710 } } // namespace v8::internal |
| OLD | NEW |