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 |