Chromium Code Reviews

Side by Side Diff: src/hydrogen.cc

Issue 23030002: Simplified BuildFastLiteral by eliminating manual allocation folding. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | test/mjsunit/fast-literal.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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...)
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...)
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...)
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...)
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...)
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | test/mjsunit/fast-literal.js » ('j') | no next file with comments »

Powered by Google App Engine