Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

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. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | 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 4078 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
This is Rietveld 408576698