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