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 4050 matching lines...) Loading... | |
4061 } | 4061 } |
4062 return false; | 4062 return false; |
4063 } | 4063 } |
4064 | 4064 |
4065 | 4065 |
4066 // Determines whether the given array or object literal boilerplate satisfies | 4066 // Determines whether the given array or object literal boilerplate satisfies |
4067 // all limits to be considered for fast deep-copying and computes the total | 4067 // all limits to be considered for fast deep-copying and computes the total |
4068 // size of all objects that are part of the graph. | 4068 // size of all objects that are part of the graph. |
4069 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 4069 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
4070 int max_depth, | 4070 int max_depth, |
4071 int* max_properties, | 4071 int* max_properties) { |
4072 int* data_size, | |
4073 int* pointer_size) { | |
4074 if (boilerplate->map()->is_deprecated()) { | 4072 if (boilerplate->map()->is_deprecated()) { |
4075 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); | 4073 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); |
4076 if (result->IsSmi()) return false; | 4074 if (result->IsSmi()) return false; |
4077 } | 4075 } |
4078 | 4076 |
4079 ASSERT(max_depth >= 0 && *max_properties >= 0); | 4077 ASSERT(max_depth >= 0 && *max_properties >= 0); |
4080 if (max_depth == 0) return false; | 4078 if (max_depth == 0) return false; |
4081 | 4079 |
4082 Isolate* isolate = boilerplate->GetIsolate(); | 4080 Isolate* isolate = boilerplate->GetIsolate(); |
4083 Handle<FixedArrayBase> elements(boilerplate->elements()); | 4081 Handle<FixedArrayBase> elements(boilerplate->elements()); |
4084 if (elements->length() > 0 && | 4082 if (elements->length() > 0 && |
4085 elements->map() != isolate->heap()->fixed_cow_array_map()) { | 4083 elements->map() != isolate->heap()->fixed_cow_array_map()) { |
4086 if (boilerplate->HasFastDoubleElements()) { | 4084 if (boilerplate->HasFastObjectElements()) { |
4087 *data_size += FixedDoubleArray::SizeFor(elements->length()); | |
4088 } else if (boilerplate->HasFastObjectElements()) { | |
4089 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 4085 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
4090 int length = elements->length(); | 4086 int length = elements->length(); |
4091 for (int i = 0; i < length; i++) { | 4087 for (int i = 0; i < length; i++) { |
4092 if ((*max_properties)-- == 0) return false; | 4088 if ((*max_properties)-- == 0) return false; |
4093 Handle<Object> value(fast_elements->get(i), isolate); | 4089 Handle<Object> value(fast_elements->get(i), isolate); |
4094 if (value->IsJSObject()) { | 4090 if (value->IsJSObject()) { |
4095 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 4091 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
4096 if (!IsFastLiteral(value_object, | 4092 if (!IsFastLiteral(value_object, |
4097 max_depth - 1, | 4093 max_depth - 1, |
4098 max_properties, | 4094 max_properties)) { |
4099 data_size, | |
4100 pointer_size)) { | |
4101 return false; | 4095 return false; |
4102 } | 4096 } |
4103 } | 4097 } |
4104 } | 4098 } |
4105 *pointer_size += FixedArray::SizeFor(length); | 4099 } else if (!boilerplate->HasFastDoubleElements()) { |
4106 } else { | |
4107 return false; | 4100 return false; |
4108 } | 4101 } |
4109 } | 4102 } |
4110 | 4103 |
4111 Handle<FixedArray> properties(boilerplate->properties()); | 4104 Handle<FixedArray> properties(boilerplate->properties()); |
4112 if (properties->length() > 0) { | 4105 if (properties->length() > 0) { |
4113 return false; | 4106 return false; |
4114 } else { | 4107 } else { |
4115 Handle<DescriptorArray> descriptors( | 4108 Handle<DescriptorArray> descriptors( |
4116 boilerplate->map()->instance_descriptors()); | 4109 boilerplate->map()->instance_descriptors()); |
4117 int limit = boilerplate->map()->NumberOfOwnDescriptors(); | 4110 int limit = boilerplate->map()->NumberOfOwnDescriptors(); |
4118 for (int i = 0; i < limit; i++) { | 4111 for (int i = 0; i < limit; i++) { |
4119 PropertyDetails details = descriptors->GetDetails(i); | 4112 PropertyDetails details = descriptors->GetDetails(i); |
4120 if (details.type() != FIELD) continue; | 4113 if (details.type() != FIELD) continue; |
4121 Representation representation = details.representation(); | |
4122 int index = descriptors->GetFieldIndex(i); | 4114 int index = descriptors->GetFieldIndex(i); |
4123 if ((*max_properties)-- == 0) return false; | 4115 if ((*max_properties)-- == 0) return false; |
4124 Handle<Object> value(boilerplate->InObjectPropertyAt(index), isolate); | 4116 Handle<Object> value(boilerplate->InObjectPropertyAt(index), isolate); |
4125 if (value->IsJSObject()) { | 4117 if (value->IsJSObject()) { |
4126 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 4118 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
4127 if (!IsFastLiteral(value_object, | 4119 if (!IsFastLiteral(value_object, |
4128 max_depth - 1, | 4120 max_depth - 1, |
4129 max_properties, | 4121 max_properties)) { |
4130 data_size, | |
4131 pointer_size)) { | |
4132 return false; | 4122 return false; |
4133 } | 4123 } |
4134 } else if (representation.IsDouble()) { | |
4135 *data_size += HeapNumber::kSize; | |
4136 } | 4124 } |
4137 } | 4125 } |
4138 } | 4126 } |
4139 | |
4140 *pointer_size += boilerplate->map()->instance_size(); | |
4141 return true; | 4127 return true; |
4142 } | 4128 } |
4143 | 4129 |
4144 | 4130 |
4145 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 4131 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
4146 ASSERT(!HasStackOverflow()); | 4132 ASSERT(!HasStackOverflow()); |
4147 ASSERT(current_block() != NULL); | 4133 ASSERT(current_block() != NULL); |
4148 ASSERT(current_block()->HasPredecessor()); | 4134 ASSERT(current_block()->HasPredecessor()); |
4149 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 4135 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
4150 HValue* context = environment()->context(); | |
4151 HInstruction* literal; | 4136 HInstruction* literal; |
4152 | 4137 |
4153 // Check whether to use fast or slow deep-copying for boilerplate. | 4138 // Check whether to use fast or slow deep-copying for boilerplate. |
4154 int data_size = 0; | |
4155 int pointer_size = 0; | |
4156 int max_properties = kMaxFastLiteralProperties; | 4139 int max_properties = kMaxFastLiteralProperties; |
4157 Handle<Object> original_boilerplate(closure->literals()->get( | 4140 Handle<Object> boilerplate(closure->literals()->get( |
4158 expr->literal_index()), isolate()); | 4141 expr->literal_index()), isolate()); |
4159 if (original_boilerplate->IsJSObject() && | 4142 if (boilerplate->IsJSObject() && |
4160 IsFastLiteral(Handle<JSObject>::cast(original_boilerplate), | 4143 IsFastLiteral(Handle<JSObject>::cast(boilerplate), |
4161 kMaxFastLiteralDepth, | 4144 kMaxFastLiteralDepth, |
4162 &max_properties, | 4145 &max_properties)) { |
4163 &data_size, | |
4164 &pointer_size)) { | |
4165 Handle<JSObject> original_boilerplate_object = | |
4166 Handle<JSObject>::cast(original_boilerplate); | |
4167 Handle<JSObject> boilerplate_object = | 4146 Handle<JSObject> boilerplate_object = |
4168 DeepCopy(original_boilerplate_object); | 4147 Handle<JSObject>::cast(boilerplate); |
4169 | 4148 |
4170 literal = BuildFastLiteral(context, | 4149 literal = BuildFastLiteral(boilerplate_object, |
4171 boilerplate_object, | |
4172 original_boilerplate_object, | |
4173 Handle<Object>::null(), | 4150 Handle<Object>::null(), |
4174 data_size, | |
4175 pointer_size, | |
4176 DONT_TRACK_ALLOCATION_SITE); | 4151 DONT_TRACK_ALLOCATION_SITE); |
4177 } else { | 4152 } else { |
4178 NoObservableSideEffectsScope no_effects(this); | 4153 NoObservableSideEffectsScope no_effects(this); |
4179 Handle<FixedArray> closure_literals(closure->literals(), isolate()); | 4154 Handle<FixedArray> closure_literals(closure->literals(), isolate()); |
4180 Handle<FixedArray> constant_properties = expr->constant_properties(); | 4155 Handle<FixedArray> constant_properties = expr->constant_properties(); |
4181 int literal_index = expr->literal_index(); | 4156 int literal_index = expr->literal_index(); |
4182 int flags = expr->fast_elements() | 4157 int flags = expr->fast_elements() |
4183 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; | 4158 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; |
4184 flags |= expr->has_function() | 4159 flags |= expr->has_function() |
4185 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; | 4160 ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags; |
(...skipping 81 matching lines...) Loading... | |
4267 } | 4242 } |
4268 } | 4243 } |
4269 | 4244 |
4270 | 4245 |
4271 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 4246 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
4272 ASSERT(!HasStackOverflow()); | 4247 ASSERT(!HasStackOverflow()); |
4273 ASSERT(current_block() != NULL); | 4248 ASSERT(current_block() != NULL); |
4274 ASSERT(current_block()->HasPredecessor()); | 4249 ASSERT(current_block()->HasPredecessor()); |
4275 ZoneList<Expression*>* subexprs = expr->values(); | 4250 ZoneList<Expression*>* subexprs = expr->values(); |
4276 int length = subexprs->length(); | 4251 int length = subexprs->length(); |
4277 HValue* context = environment()->context(); | |
4278 HInstruction* literal; | 4252 HInstruction* literal; |
4279 | 4253 |
4280 Handle<AllocationSite> site; | 4254 Handle<AllocationSite> site; |
4281 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); | 4255 Handle<FixedArray> literals(environment()->closure()->literals(), isolate()); |
4282 bool uninitialized = false; | 4256 bool uninitialized = false; |
4283 Handle<Object> literals_cell(literals->get(expr->literal_index()), | 4257 Handle<Object> literals_cell(literals->get(expr->literal_index()), |
4284 isolate()); | 4258 isolate()); |
4285 Handle<Object> raw_boilerplate; | 4259 Handle<Object> raw_boilerplate; |
4286 if (literals_cell->IsUndefined()) { | 4260 if (literals_cell->IsUndefined()) { |
4287 uninitialized = true; | 4261 uninitialized = true; |
(...skipping 13 matching lines...) Loading... | |
4301 } | 4275 } |
4302 } else { | 4276 } else { |
4303 ASSERT(literals_cell->IsAllocationSite()); | 4277 ASSERT(literals_cell->IsAllocationSite()); |
4304 site = Handle<AllocationSite>::cast(literals_cell); | 4278 site = Handle<AllocationSite>::cast(literals_cell); |
4305 raw_boilerplate = Handle<Object>(site->transition_info(), isolate()); | 4279 raw_boilerplate = Handle<Object>(site->transition_info(), isolate()); |
4306 } | 4280 } |
4307 | 4281 |
4308 ASSERT(!raw_boilerplate.is_null()); | 4282 ASSERT(!raw_boilerplate.is_null()); |
4309 ASSERT(site->IsLiteralSite()); | 4283 ASSERT(site->IsLiteralSite()); |
4310 | 4284 |
4311 Handle<JSObject> original_boilerplate_object = | 4285 Handle<JSObject> boilerplate_object = |
4312 Handle<JSObject>::cast(raw_boilerplate); | 4286 Handle<JSObject>::cast(raw_boilerplate); |
4313 ElementsKind boilerplate_elements_kind = | 4287 ElementsKind boilerplate_elements_kind = |
4314 Handle<JSObject>::cast(original_boilerplate_object)->GetElementsKind(); | 4288 Handle<JSObject>::cast(boilerplate_object)->GetElementsKind(); |
4315 | 4289 |
4316 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 4290 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
4317 // end, we want to quit creating allocation site info after a certain number | 4291 // end, we want to quit creating allocation site info after a certain number |
4318 // of GCs for a call site. | 4292 // of GCs for a call site. |
4319 AllocationSiteMode mode = AllocationSite::GetMode( | 4293 AllocationSiteMode mode = AllocationSite::GetMode( |
4320 boilerplate_elements_kind); | 4294 boilerplate_elements_kind); |
4321 | 4295 |
4322 // Check whether to use fast or slow deep-copying for boilerplate. | 4296 // Check whether to use fast or slow deep-copying for boilerplate. |
4323 int data_size = 0; | |
4324 int pointer_size = 0; | |
4325 int max_properties = kMaxFastLiteralProperties; | 4297 int max_properties = kMaxFastLiteralProperties; |
4326 if (IsFastLiteral(original_boilerplate_object, | 4298 if (IsFastLiteral(boilerplate_object, |
4327 kMaxFastLiteralDepth, | 4299 kMaxFastLiteralDepth, |
4328 &max_properties, | 4300 &max_properties)) { |
4329 &data_size, | 4301 literal = BuildFastLiteral(boilerplate_object, |
4330 &pointer_size)) { | |
4331 if (mode == TRACK_ALLOCATION_SITE) { | |
4332 pointer_size += AllocationMemento::kSize; | |
4333 } | |
4334 | |
4335 Handle<JSObject> boilerplate_object = DeepCopy(original_boilerplate_object); | |
4336 literal = BuildFastLiteral(context, | |
4337 boilerplate_object, | |
4338 original_boilerplate_object, | |
4339 site, | 4302 site, |
4340 data_size, | |
4341 pointer_size, | |
4342 mode); | 4303 mode); |
4343 } else { | 4304 } else { |
4344 NoObservableSideEffectsScope no_effects(this); | 4305 NoObservableSideEffectsScope no_effects(this); |
4345 // Boilerplate already exists and constant elements are never accessed, | 4306 // Boilerplate already exists and constant elements are never accessed, |
4346 // pass an empty fixed array to the runtime function instead. | 4307 // pass an empty fixed array to the runtime function instead. |
4347 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 4308 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
4348 int literal_index = expr->literal_index(); | 4309 int literal_index = expr->literal_index(); |
4349 | 4310 |
4350 Add<HPushArgument>(Add<HConstant>(literals)); | 4311 Add<HPushArgument>(Add<HConstant>(literals)); |
4351 Add<HPushArgument>(Add<HConstant>(literal_index)); | 4312 Add<HPushArgument>(Add<HConstant>(literal_index)); |
4352 Add<HPushArgument>(Add<HConstant>(constants)); | 4313 Add<HPushArgument>(Add<HConstant>(constants)); |
4353 | 4314 |
4354 Runtime::FunctionId function_id = (expr->depth() > 1) | 4315 Runtime::FunctionId function_id = (expr->depth() > 1) |
4355 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 4316 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
4356 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), | 4317 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), |
4357 Runtime::FunctionForId(function_id), | 4318 Runtime::FunctionForId(function_id), |
4358 3); | 4319 3); |
4359 | 4320 |
4360 // De-opt if elements kind changed from boilerplate_elements_kind. | 4321 // De-opt if elements kind changed from boilerplate_elements_kind. |
4361 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), | 4322 Handle<Map> map = Handle<Map>(boilerplate_object->map(), |
Michael Starzinger
2013/08/28 08:50:59
nit: Should fit into one line now.
| |
4362 isolate()); | 4323 isolate()); |
4363 literal = Add<HCheckMaps>(literal, map, top_info()); | 4324 literal = Add<HCheckMaps>(literal, map, top_info()); |
4364 } | 4325 } |
4365 | 4326 |
4366 // The array is expected in the bailout environment during computation | 4327 // The array is expected in the bailout environment during computation |
4367 // of the property values and is the value of the entire expression. | 4328 // of the property values and is the value of the entire expression. |
4368 Push(literal); | 4329 Push(literal); |
4369 // The literal index is on the stack, too. | 4330 // The literal index is on the stack, too. |
4370 Push(Add<HConstant>(expr->literal_index())); | 4331 Push(Add<HConstant>(expr->literal_index())); |
4371 | 4332 |
(...skipping 3876 matching lines...) Loading... | |
8248 if (function_state()->outer() != NULL) { | 8209 if (function_state()->outer() != NULL) { |
8249 return New<HConstant>( | 8210 return New<HConstant>( |
8250 function_state()->compilation_info()->closure()); | 8211 function_state()->compilation_info()->closure()); |
8251 } else { | 8212 } else { |
8252 return new(zone()) HThisFunction; | 8213 return new(zone()) HThisFunction; |
8253 } | 8214 } |
8254 } | 8215 } |
8255 | 8216 |
8256 | 8217 |
8257 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 8218 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
8258 HValue* context, | |
8259 Handle<JSObject> boilerplate_object, | 8219 Handle<JSObject> boilerplate_object, |
8260 Handle<JSObject> original_boilerplate_object, | 8220 Handle<Object> allocation_site_object, |
8261 Handle<Object> allocation_site, | |
8262 int data_size, | |
8263 int pointer_size, | |
8264 AllocationSiteMode mode) { | 8221 AllocationSiteMode mode) { |
8265 NoObservableSideEffectsScope no_effects(this); | 8222 NoObservableSideEffectsScope no_effects(this); |
8266 | 8223 |
8267 HInstruction* target = NULL; | 8224 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
8268 HInstruction* data_target = NULL; | 8225 int object_size = boilerplate_object->map()->instance_size(); |
8226 int object_offset = object_size; | |
8269 | 8227 |
8270 if (isolate()->heap()->GetPretenureMode() == TENURED) { | |
8271 if (data_size != 0) { | |
8272 HValue* size_in_bytes = Add<HConstant>(data_size); | |
8273 data_target = Add<HAllocate>(size_in_bytes, HType::JSObject(), TENURED, | |
8274 FIXED_DOUBLE_ARRAY_TYPE); | |
8275 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); | |
8276 AddStoreMapConstant(data_target, free_space_map); | |
8277 HObjectAccess access = | |
8278 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); | |
8279 Add<HStoreNamedField>(data_target, access, size_in_bytes); | |
8280 } | |
8281 if (pointer_size != 0) { | |
8282 HValue* size_in_bytes = Add<HConstant>(pointer_size); | |
8283 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), TENURED, | |
8284 JS_OBJECT_TYPE); | |
8285 } | |
8286 } else { | |
8287 InstanceType instance_type = boilerplate_object->map()->instance_type(); | |
8288 HValue* size_in_bytes = Add<HConstant>(data_size + pointer_size); | |
8289 target = Add<HAllocate>(size_in_bytes, HType::JSObject(), NOT_TENURED, | |
8290 instance_type); | |
8291 } | |
8292 | |
8293 int offset = 0; | |
8294 int data_offset = 0; | |
8295 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, | |
8296 allocation_site, target, &offset, data_target, | |
8297 &data_offset, mode); | |
8298 return target; | |
8299 } | |
8300 | |
8301 | |
8302 void HOptimizedGraphBuilder::BuildEmitDeepCopy( | |
8303 Handle<JSObject> boilerplate_object, | |
8304 Handle<JSObject> original_boilerplate_object, | |
8305 Handle<Object> allocation_site_object, | |
8306 HInstruction* target, | |
8307 int* offset, | |
8308 HInstruction* data_target, | |
8309 int* data_offset, | |
8310 AllocationSiteMode mode) { | |
8311 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && | 8228 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && |
8312 boilerplate_object->map()->CanTrackAllocationSite(); | 8229 boilerplate_object->map()->CanTrackAllocationSite(); |
8313 | 8230 |
8314 // If using allocation sites, then the payload on the site should already | 8231 // If using allocation sites, then the payload on the site should already |
8315 // be filled in as a valid (boilerplate) array. | 8232 // be filled in as a valid (boilerplate) array. |
8316 ASSERT(!create_allocation_site_info || | 8233 ASSERT(!create_allocation_site_info || |
8317 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); | 8234 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); |
8318 | 8235 |
8319 HInstruction* allocation_site = NULL; | 8236 if (create_allocation_site_info) { |
8237 object_size += AllocationMemento::kSize; | |
8238 } | |
8239 | |
8240 HValue* object_size_constant = Add<HConstant>(object_size); | |
8241 HInstruction* object = Add<HAllocate>(object_size_constant, HType::JSObject(), | |
8242 isolate()->heap()->GetPretenureMode(), JS_OBJECT_TYPE); | |
8320 | 8243 |
8321 if (create_allocation_site_info) { | 8244 if (create_allocation_site_info) { |
8322 allocation_site = Add<HConstant>(allocation_site_object); | 8245 HInstruction* allocation_site = Add<HConstant>(allocation_site_object); |
8246 BuildCreateAllocationMemento(object, object_offset, allocation_site); | |
8323 } | 8247 } |
8324 | 8248 |
8325 // Only elements backing stores for non-COW arrays need to be copied. | |
8326 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | |
8327 Handle<FixedArrayBase> original_elements( | |
8328 original_boilerplate_object->elements()); | |
8329 ElementsKind kind = boilerplate_object->map()->elements_kind(); | |
8330 | |
8331 int object_offset = *offset; | |
8332 int object_size = boilerplate_object->map()->instance_size(); | |
8333 int elements_size = (elements->length() > 0 && | 8249 int elements_size = (elements->length() > 0 && |
8334 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 8250 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
8335 elements->Size() : 0; | 8251 elements->Size() : 0; |
8336 int elements_offset = 0; | |
8337 | 8252 |
8338 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { | 8253 HInstruction* object_elements = NULL; |
8339 elements_offset = *data_offset; | 8254 if (elements_size > 0) { |
8340 *data_offset += elements_size; | 8255 HValue* object_elements_size = Add<HConstant>(elements_size); |
8341 } else { | 8256 if (boilerplate_object->HasFastDoubleElements()) { |
8342 // Place elements right after this object. | 8257 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), |
8343 elements_offset = *offset + object_size; | 8258 isolate()->heap()->GetPretenureMode(), FIXED_DOUBLE_ARRAY_TYPE); |
8344 *offset += elements_size; | 8259 } else { |
8260 object_elements = Add<HAllocate>(object_elements_size, HType::JSObject(), | |
8261 isolate()->heap()->GetPretenureMode(), FIXED_ARRAY_TYPE); | |
8262 } | |
8345 } | 8263 } |
8346 // Increase the offset so that subsequent objects end up right after this | |
8347 // object (and it's elements if they are allocated in the same space). | |
8348 *offset += object_size; | |
8349 | 8264 |
8350 // Copy object elements if non-COW. | 8265 // Copy object elements if non-COW. |
8351 HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target, | 8266 BuildEmitObjectHeader(boilerplate_object, object, object_elements); |
8352 data_target, object_offset, elements_offset, elements_size); | |
8353 if (object_elements != NULL) { | 8267 if (object_elements != NULL) { |
8354 BuildEmitElements(elements, original_elements, kind, object_elements, | 8268 BuildEmitElements(boilerplate_object, elements, object_elements); |
8355 target, offset, data_target, data_offset); | |
8356 } | 8269 } |
8357 | 8270 |
8358 // Copy in-object properties. | 8271 // Copy in-object properties. |
8359 if (boilerplate_object->map()->NumberOfFields() != 0) { | 8272 if (boilerplate_object->map()->NumberOfFields() != 0) { |
8360 HValue* object_properties = | 8273 BuildEmitInObjectProperties(boilerplate_object, object); |
8361 Add<HInnerAllocatedObject>(target, object_offset); | |
8362 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, | |
8363 object_properties, target, offset, data_target, data_offset); | |
8364 } | 8274 } |
8365 | 8275 return object; |
8366 // Create allocation site info. | |
8367 if (mode == TRACK_ALLOCATION_SITE && | |
8368 boilerplate_object->map()->CanTrackAllocationSite()) { | |
8369 elements_offset += AllocationMemento::kSize; | |
8370 *offset += AllocationMemento::kSize; | |
8371 BuildCreateAllocationMemento(target, JSArray::kSize, allocation_site); | |
8372 } | |
8373 } | 8276 } |
8374 | 8277 |
8375 | 8278 |
8376 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( | 8279 void HOptimizedGraphBuilder::BuildEmitObjectHeader( |
8377 Handle<JSObject> boilerplate_object, | 8280 Handle<JSObject> boilerplate_object, |
8378 HInstruction* target, | 8281 HInstruction* object, |
8379 HInstruction* data_target, | 8282 HInstruction* object_elements) { |
8380 int object_offset, | |
8381 int elements_offset, | |
8382 int elements_size) { | |
8383 ASSERT(boilerplate_object->properties()->length() == 0); | 8283 ASSERT(boilerplate_object->properties()->length() == 0); |
8384 HValue* result = NULL; | |
8385 | 8284 |
8386 HValue* object_header = Add<HInnerAllocatedObject>(target, object_offset); | |
8387 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 8285 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
8388 AddStoreMapConstant(object_header, boilerplate_object_map); | 8286 AddStoreMapConstant(object, boilerplate_object_map); |
8389 | 8287 |
8390 HInstruction* elements; | 8288 if (object_elements == NULL) { |
8391 if (elements_size == 0) { | |
8392 Handle<Object> elements_field = | 8289 Handle<Object> elements_field = |
8393 Handle<Object>(boilerplate_object->elements(), isolate()); | 8290 Handle<Object>(boilerplate_object->elements(), isolate()); |
8394 elements = Add<HConstant>(elements_field); | 8291 object_elements = Add<HConstant>(elements_field); |
8395 } else { | |
8396 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { | |
8397 elements = Add<HInnerAllocatedObject>(data_target, elements_offset); | |
8398 } else { | |
8399 elements = Add<HInnerAllocatedObject>(target, elements_offset); | |
8400 } | |
8401 result = elements; | |
8402 } | 8292 } |
8403 Add<HStoreNamedField>(object_header, HObjectAccess::ForElementsPointer(), | 8293 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
8404 elements); | 8294 object_elements); |
8405 | 8295 |
8406 Handle<Object> properties_field = | 8296 Handle<Object> properties_field = |
8407 Handle<Object>(boilerplate_object->properties(), isolate()); | 8297 Handle<Object>(boilerplate_object->properties(), isolate()); |
8408 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 8298 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
8409 HInstruction* properties = Add<HConstant>(properties_field); | 8299 HInstruction* properties = Add<HConstant>(properties_field); |
8410 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 8300 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
8411 Add<HStoreNamedField>(object_header, access, properties); | 8301 Add<HStoreNamedField>(object, access, properties); |
8412 | 8302 |
8413 if (boilerplate_object->IsJSArray()) { | 8303 if (boilerplate_object->IsJSArray()) { |
8414 Handle<JSArray> boilerplate_array = | 8304 Handle<JSArray> boilerplate_array = |
8415 Handle<JSArray>::cast(boilerplate_object); | 8305 Handle<JSArray>::cast(boilerplate_object); |
8416 Handle<Object> length_field = | 8306 Handle<Object> length_field = |
8417 Handle<Object>(boilerplate_array->length(), isolate()); | 8307 Handle<Object>(boilerplate_array->length(), isolate()); |
8418 HInstruction* length = Add<HConstant>(length_field); | 8308 HInstruction* length = Add<HConstant>(length_field); |
8419 | 8309 |
8420 ASSERT(boilerplate_array->length()->IsSmi()); | 8310 ASSERT(boilerplate_array->length()->IsSmi()); |
8421 Add<HStoreNamedField>(object_header, HObjectAccess::ForArrayLength( | 8311 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength( |
8422 boilerplate_array->GetElementsKind()), length); | 8312 boilerplate_array->GetElementsKind()), length); |
8423 } | 8313 } |
8424 | |
8425 return result; | |
8426 } | 8314 } |
8427 | 8315 |
8428 | 8316 |
8429 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 8317 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
8430 Handle<JSObject> boilerplate_object, | 8318 Handle<JSObject> boilerplate_object, |
8431 Handle<JSObject> original_boilerplate_object, | 8319 HInstruction* object) { |
8432 HValue* object_properties, | |
8433 HInstruction* target, | |
8434 int* offset, | |
8435 HInstruction* data_target, | |
8436 int* data_offset) { | |
8437 Handle<DescriptorArray> descriptors( | 8320 Handle<DescriptorArray> descriptors( |
8438 boilerplate_object->map()->instance_descriptors()); | 8321 boilerplate_object->map()->instance_descriptors()); |
8439 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); | 8322 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); |
8440 | 8323 |
8441 int copied_fields = 0; | 8324 int copied_fields = 0; |
8442 for (int i = 0; i < limit; i++) { | 8325 for (int i = 0; i < limit; i++) { |
8443 PropertyDetails details = descriptors->GetDetails(i); | 8326 PropertyDetails details = descriptors->GetDetails(i); |
8444 if (details.type() != FIELD) continue; | 8327 if (details.type() != FIELD) continue; |
8445 copied_fields++; | 8328 copied_fields++; |
8446 int index = descriptors->GetFieldIndex(i); | 8329 int index = descriptors->GetFieldIndex(i); |
8447 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); | 8330 int property_offset = boilerplate_object->GetInObjectPropertyOffset(index); |
8448 Handle<Name> name(descriptors->GetKey(i)); | 8331 Handle<Name> name(descriptors->GetKey(i)); |
8449 Handle<Object> value = | 8332 Handle<Object> value = |
8450 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), | 8333 Handle<Object>(boilerplate_object->InObjectPropertyAt(index), |
8451 isolate()); | 8334 isolate()); |
8452 | 8335 |
8453 // The access for the store depends on the type of the boilerplate. | 8336 // The access for the store depends on the type of the boilerplate. |
8454 HObjectAccess access = boilerplate_object->IsJSArray() ? | 8337 HObjectAccess access = boilerplate_object->IsJSArray() ? |
8455 HObjectAccess::ForJSArrayOffset(property_offset) : | 8338 HObjectAccess::ForJSArrayOffset(property_offset) : |
8456 HObjectAccess::ForJSObjectOffset(property_offset); | 8339 HObjectAccess::ForJSObjectOffset(property_offset); |
8457 | 8340 |
8458 if (value->IsJSObject()) { | 8341 if (value->IsJSObject()) { |
8459 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 8342 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
8460 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 8343 HInstruction* result = |
8461 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), | 8344 BuildFastLiteral(value_object, |
8462 isolate())); | 8345 Handle<Object>::null(), DONT_TRACK_ALLOCATION_SITE); |
8463 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, | 8346 Add<HStoreNamedField>(object, access, result); |
8464 *offset); | |
8465 | |
8466 Add<HStoreNamedField>(object_properties, access, value_instruction); | |
8467 BuildEmitDeepCopy(value_object, original_value_object, | |
8468 Handle<Object>::null(), target, | |
8469 offset, data_target, data_offset, | |
8470 DONT_TRACK_ALLOCATION_SITE); | |
8471 } else { | 8347 } else { |
8472 Representation representation = details.representation(); | 8348 Representation representation = details.representation(); |
8473 HInstruction* value_instruction = Add<HConstant>(value); | 8349 HInstruction* value_instruction = Add<HConstant>(value); |
8474 | 8350 |
8475 if (representation.IsDouble()) { | 8351 if (representation.IsDouble()) { |
8476 // Allocate a HeapNumber box and store the value into it. | 8352 // Allocate a HeapNumber box and store the value into it. |
8477 HInstruction* double_box; | 8353 HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize); |
8478 if (data_target != NULL) { | 8354 HInstruction* double_box = |
8479 double_box = Add<HInnerAllocatedObject>(data_target, *data_offset); | 8355 Add<HAllocate>(heap_number_constant, HType::HeapNumber(), |
8480 *data_offset += HeapNumber::kSize; | 8356 isolate()->heap()->GetPretenureMode(), HEAP_NUMBER_TYPE); |
8481 } else { | |
8482 double_box = Add<HInnerAllocatedObject>(target, *offset); | |
8483 *offset += HeapNumber::kSize; | |
8484 } | |
8485 AddStoreMapConstant(double_box, | 8357 AddStoreMapConstant(double_box, |
8486 isolate()->factory()->heap_number_map()); | 8358 isolate()->factory()->heap_number_map()); |
8487 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), | 8359 Add<HStoreNamedField>(double_box, HObjectAccess::ForHeapNumberValue(), |
8488 value_instruction); | 8360 value_instruction); |
8489 value_instruction = double_box; | 8361 value_instruction = double_box; |
8490 } | 8362 } |
8491 | 8363 |
8492 Add<HStoreNamedField>(object_properties, access, value_instruction); | 8364 Add<HStoreNamedField>(object, access, value_instruction); |
8493 } | 8365 } |
8494 } | 8366 } |
8495 | 8367 |
8496 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 8368 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
8497 HInstruction* value_instruction = | 8369 HInstruction* value_instruction = |
8498 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); | 8370 Add<HConstant>(isolate()->factory()->one_pointer_filler_map()); |
8499 for (int i = copied_fields; i < inobject_properties; i++) { | 8371 for (int i = copied_fields; i < inobject_properties; i++) { |
8500 ASSERT(boilerplate_object->IsJSObject()); | 8372 ASSERT(boilerplate_object->IsJSObject()); |
8501 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 8373 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
8502 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 8374 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
8503 Add<HStoreNamedField>(object_properties, access, value_instruction); | 8375 Add<HStoreNamedField>(object, access, value_instruction); |
8504 } | 8376 } |
8505 } | 8377 } |
8506 | 8378 |
8507 | 8379 |
8508 void HOptimizedGraphBuilder::BuildEmitElements( | 8380 void HOptimizedGraphBuilder::BuildEmitElements( |
8381 Handle<JSObject> boilerplate_object, | |
8509 Handle<FixedArrayBase> elements, | 8382 Handle<FixedArrayBase> elements, |
8510 Handle<FixedArrayBase> original_elements, | 8383 HValue* object_elements) { |
8511 ElementsKind kind, | 8384 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
8512 HValue* object_elements, | |
8513 HInstruction* target, | |
8514 int* offset, | |
8515 HInstruction* data_target, | |
8516 int* data_offset) { | |
8517 int elements_length = elements->length(); | 8385 int elements_length = elements->length(); |
8518 HValue* object_elements_length = Add<HConstant>(elements_length); | 8386 HValue* object_elements_length = Add<HConstant>(elements_length); |
8519 | |
8520 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); | 8387 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); |
8521 | 8388 |
8522 // Copy elements backing store content. | 8389 // Copy elements backing store content. |
8523 if (elements->IsFixedDoubleArray()) { | 8390 if (elements->IsFixedDoubleArray()) { |
8524 BuildEmitFixedDoubleArray(elements, kind, object_elements); | 8391 BuildEmitFixedDoubleArray(elements, kind, object_elements); |
8525 } else if (elements->IsFixedArray()) { | 8392 } else if (elements->IsFixedArray()) { |
8526 BuildEmitFixedArray(elements, original_elements, kind, object_elements, | 8393 BuildEmitFixedArray(elements, kind, object_elements); |
8527 target, offset, data_target, data_offset); | |
8528 } else { | 8394 } else { |
8529 UNREACHABLE(); | 8395 UNREACHABLE(); |
8530 } | 8396 } |
8531 } | 8397 } |
8532 | 8398 |
8533 | 8399 |
8534 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( | 8400 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( |
8535 Handle<FixedArrayBase> elements, | 8401 Handle<FixedArrayBase> elements, |
8536 ElementsKind kind, | 8402 ElementsKind kind, |
8537 HValue* object_elements) { | 8403 HValue* object_elements) { |
8538 HInstruction* boilerplate_elements = Add<HConstant>(elements); | 8404 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
8539 int elements_length = elements->length(); | 8405 int elements_length = elements->length(); |
8540 for (int i = 0; i < elements_length; i++) { | 8406 for (int i = 0; i < elements_length; i++) { |
8541 HValue* key_constant = Add<HConstant>(i); | 8407 HValue* key_constant = Add<HConstant>(i); |
8542 HInstruction* value_instruction = | 8408 HInstruction* value_instruction = |
8543 Add<HLoadKeyed>(boilerplate_elements, key_constant, | 8409 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
8544 static_cast<HValue*>(NULL), kind, | 8410 static_cast<HValue*>(NULL), kind, |
8545 ALLOW_RETURN_HOLE); | 8411 ALLOW_RETURN_HOLE); |
8546 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant, | 8412 HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant, |
8547 value_instruction, kind); | 8413 value_instruction, kind); |
8548 store->SetFlag(HValue::kAllowUndefinedAsNaN); | 8414 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
8549 } | 8415 } |
8550 } | 8416 } |
8551 | 8417 |
8552 | 8418 |
8553 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 8419 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
8554 Handle<FixedArrayBase> elements, | 8420 Handle<FixedArrayBase> elements, |
8555 Handle<FixedArrayBase> original_elements, | |
8556 ElementsKind kind, | 8421 ElementsKind kind, |
8557 HValue* object_elements, | 8422 HValue* object_elements) { |
8558 HInstruction* target, | |
8559 int* offset, | |
8560 HInstruction* data_target, | |
8561 int* data_offset) { | |
8562 HInstruction* boilerplate_elements = Add<HConstant>(elements); | 8423 HInstruction* boilerplate_elements = Add<HConstant>(elements); |
8563 int elements_length = elements->length(); | 8424 int elements_length = elements->length(); |
8564 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 8425 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
8565 Handle<FixedArray> original_fast_elements = | |
8566 Handle<FixedArray>::cast(original_elements); | |
8567 for (int i = 0; i < elements_length; i++) { | 8426 for (int i = 0; i < elements_length; i++) { |
8568 Handle<Object> value(fast_elements->get(i), isolate()); | 8427 Handle<Object> value(fast_elements->get(i), isolate()); |
8569 HValue* key_constant = Add<HConstant>(i); | 8428 HValue* key_constant = Add<HConstant>(i); |
8570 if (value->IsJSObject()) { | 8429 if (value->IsJSObject()) { |
8571 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 8430 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
8572 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 8431 HInstruction* result = |
8573 Handle<Object>(original_fast_elements->get(i), isolate())); | 8432 BuildFastLiteral(value_object, |
8574 HInstruction* value_instruction = Add<HInnerAllocatedObject>(target, | 8433 Handle<Object>::null(), DONT_TRACK_ALLOCATION_SITE); |
8575 *offset); | 8434 Add<HStoreKeyed>(object_elements, key_constant, result, kind); |
8576 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); | |
8577 BuildEmitDeepCopy(value_object, original_value_object, | |
8578 Handle<Object>::null(), target, | |
8579 offset, data_target, data_offset, | |
8580 DONT_TRACK_ALLOCATION_SITE); | |
8581 } else { | 8435 } else { |
8582 HInstruction* value_instruction = | 8436 HInstruction* value_instruction = |
8583 Add<HLoadKeyed>(boilerplate_elements, key_constant, | 8437 Add<HLoadKeyed>(boilerplate_elements, key_constant, |
8584 static_cast<HValue*>(NULL), kind, | 8438 static_cast<HValue*>(NULL), kind, |
8585 ALLOW_RETURN_HOLE); | 8439 ALLOW_RETURN_HOLE); |
8586 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); | 8440 Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind); |
8587 } | 8441 } |
8588 } | 8442 } |
8589 } | 8443 } |
8590 | 8444 |
(...skipping 1274 matching lines...) Loading... | |
9865 if (ShouldProduceTraceOutput()) { | 9719 if (ShouldProduceTraceOutput()) { |
9866 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9720 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9867 } | 9721 } |
9868 | 9722 |
9869 #ifdef DEBUG | 9723 #ifdef DEBUG |
9870 graph_->Verify(false); // No full verify. | 9724 graph_->Verify(false); // No full verify. |
9871 #endif | 9725 #endif |
9872 } | 9726 } |
9873 | 9727 |
9874 } } // namespace v8::internal | 9728 } } // namespace v8::internal |
OLD | NEW |