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/x64/lithium-codegen-x64.cc

Issue 12114054: Supporting AllocationSiteInfo for Nested arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Some updates Created 7 years, 10 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
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 5059 matching lines...) Expand 10 before | Expand all | Expand 10 after
5070 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 5070 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
5071 // Load the map's "bit field 2". 5071 // Load the map's "bit field 2".
5072 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); 5072 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset));
5073 // Retrieve elements_kind from bit field 2. 5073 // Retrieve elements_kind from bit field 2.
5074 __ and_(rbx, Immediate(Map::kElementsKindMask)); 5074 __ and_(rbx, Immediate(Map::kElementsKindMask));
5075 __ cmpb(rbx, Immediate(boilerplate_elements_kind << 5075 __ cmpb(rbx, Immediate(boilerplate_elements_kind <<
5076 Map::kElementsKindShift)); 5076 Map::kElementsKindShift));
5077 DeoptimizeIf(not_equal, instr->environment()); 5077 DeoptimizeIf(not_equal, instr->environment());
5078 } 5078 }
5079 5079
5080 int flags = allocation_site_mode == TRACK_ALLOCATION_SITE
5081 ? ArrayLiteral::kAllocationSiteInfoAllowed
5082 : ArrayLiteral::kNoFlags;
5083
5080 // Set up the parameters to the stub/runtime call. 5084 // Set up the parameters to the stub/runtime call.
5081 __ PushHeapObject(literals); 5085 __ PushHeapObject(literals);
5082 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 5086 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
5083 // Boilerplate already exists, constant elements are never accessed. 5087 // Boilerplate already exists, constant elements are never accessed.
5084 // Pass an empty fixed array. 5088 // Pass an empty fixed array.
5085 __ Push(isolate()->factory()->empty_fixed_array()); 5089 __ Push(isolate()->factory()->empty_fixed_array());
5086 5090
5087 // Pick the right runtime function or stub to call. 5091 // Pick the right runtime function or stub to call.
5088 int length = instr->hydrogen()->length(); 5092 int length = instr->hydrogen()->length();
5089 if (instr->hydrogen()->IsCopyOnWrite()) { 5093 if (instr->hydrogen()->IsCopyOnWrite()) {
5090 ASSERT(instr->hydrogen()->depth() == 1); 5094 ASSERT(instr->hydrogen()->depth() == 1);
5091 FastCloneShallowArrayStub::Mode mode = 5095 FastCloneShallowArrayStub::Mode mode =
5092 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 5096 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
5093 FastCloneShallowArrayStub stub(mode, DONT_TRACK_ALLOCATION_SITE, length); 5097 FastCloneShallowArrayStub stub(mode, DONT_TRACK_ALLOCATION_SITE, length);
5094 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 5098 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5095 } else if (instr->hydrogen()->depth() > 1) { 5099 } else if (instr->hydrogen()->depth() > 1) {
5096 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); 5100 __ Push(Smi::FromInt(flags));
5101 CallRuntime(Runtime::kCreateArrayLiteral, 4, instr);
5097 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 5102 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
5098 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); 5103 __ Push(Smi::FromInt(flags));
5104 CallRuntime(Runtime::kCreateArrayLiteralShallow, 4, instr);
5099 } else { 5105 } else {
5100 FastCloneShallowArrayStub::Mode mode = 5106 FastCloneShallowArrayStub::Mode mode =
5101 boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS 5107 boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS
5102 ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS 5108 ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
5103 : FastCloneShallowArrayStub::CLONE_ELEMENTS; 5109 : FastCloneShallowArrayStub::CLONE_ELEMENTS;
5104 FastCloneShallowArrayStub stub(mode, allocation_site_mode, length); 5110 FastCloneShallowArrayStub stub(mode, allocation_site_mode, length);
5105 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 5111 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5106 } 5112 }
5107 } 5113 }
5108 5114
5109 5115
5110 void LCodeGen::EmitDeepCopy(Handle<JSObject> object, 5116 void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
5117 Handle<JSObject> original_object,
5111 Register result, 5118 Register result,
5112 Register source, 5119 Register source,
5113 int* offset, 5120 int* offset,
5114 AllocationSiteMode mode) { 5121 AllocationSiteMode mode) {
5115 ASSERT(!source.is(rcx)); 5122 ASSERT(!source.is(rcx));
5116 ASSERT(!result.is(rcx)); 5123 ASSERT(!result.is(rcx));
5117 5124
5125 // Should we track allocation info for *this* object in the tree?
5118 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && 5126 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
5119 object->map()->CanTrackAllocationSite(); 5127 object->IsJSArray() && object->ShouldTrackAllocationInfo();
5120 5128
5121 // Only elements backing stores for non-COW arrays need to be copied. 5129 // Only elements backing stores for non-COW arrays need to be copied.
5122 Handle<FixedArrayBase> elements(object->elements()); 5130 Handle<FixedArrayBase> elements(object->elements());
5131 Handle<FixedArrayBase> original_elements(original_object->elements());
5123 bool has_elements = elements->length() > 0 && 5132 bool has_elements = elements->length() > 0 &&
5124 elements->map() != isolate()->heap()->fixed_cow_array_map(); 5133 elements->map() != isolate()->heap()->fixed_cow_array_map();
5125 5134
5126 // Increase the offset so that subsequent objects end up right after 5135 // Increase the offset so that subsequent objects end up right after
5127 // this object and its backing store. 5136 // this object and its backing store.
5128 int object_offset = *offset; 5137 int object_offset = *offset;
5129 int object_size = object->map()->instance_size(); 5138 int object_size = object->map()->instance_size();
5130 int elements_size = has_elements ? elements->Size() : 0; 5139 int elements_size = has_elements ? elements->Size() : 0;
5131 int elements_offset = *offset + object_size; 5140 int elements_offset = *offset + object_size;
5132 if (create_allocation_site_info) { 5141 if (create_allocation_site_info) {
(...skipping 15 matching lines...) Expand all
5148 } 5157 }
5149 __ movq(FieldOperand(result, object_offset + i), rcx); 5158 __ movq(FieldOperand(result, object_offset + i), rcx);
5150 } 5159 }
5151 5160
5152 // Copy in-object properties. 5161 // Copy in-object properties.
5153 for (int i = 0; i < inobject_properties; i++) { 5162 for (int i = 0; i < inobject_properties; i++) {
5154 int total_offset = object_offset + object->GetInObjectPropertyOffset(i); 5163 int total_offset = object_offset + object->GetInObjectPropertyOffset(i);
5155 Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i)); 5164 Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i));
5156 if (value->IsJSObject()) { 5165 if (value->IsJSObject()) {
5157 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 5166 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5167 Handle<JSObject> original_value_object = Handle<JSObject>::cast(
5168 Handle<Object>(original_object->InObjectPropertyAt(i)));
5169
5158 __ lea(rcx, Operand(result, *offset)); 5170 __ lea(rcx, Operand(result, *offset));
5159 __ movq(FieldOperand(result, total_offset), rcx); 5171 __ movq(FieldOperand(result, total_offset), rcx);
5160 __ LoadHeapObject(source, value_object); 5172 __ LoadHeapObject(source, value_object);
5161 EmitDeepCopy(value_object, result, source, offset, 5173 EmitDeepCopy(value_object, original_value_object, result, source,
5162 DONT_TRACK_ALLOCATION_SITE); 5174 offset, mode);
5163 } else if (value->IsHeapObject()) { 5175 } else if (value->IsHeapObject()) {
5164 __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value)); 5176 __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value));
5165 __ movq(FieldOperand(result, total_offset), rcx); 5177 __ movq(FieldOperand(result, total_offset), rcx);
5166 } else { 5178 } else {
5167 __ movq(rcx, value, RelocInfo::NONE64); 5179 __ movq(rcx, value, RelocInfo::NONE64);
5168 __ movq(FieldOperand(result, total_offset), rcx); 5180 __ movq(FieldOperand(result, total_offset), rcx);
5169 } 5181 }
5170 } 5182 }
5171 5183
5172 // Build Allocation Site Info if desired 5184 // Build Allocation Site Info if desired
5173 if (create_allocation_site_info) { 5185 if (create_allocation_site_info) {
5174 __ LoadRoot(kScratchRegister, Heap::kAllocationSiteInfoMapRootIndex); 5186 __ LoadRoot(kScratchRegister, Heap::kAllocationSiteInfoMapRootIndex);
5175 __ movq(FieldOperand(result, object_size), kScratchRegister); 5187 __ movq(FieldOperand(result, object_size + object_offset),
5176 __ movq(FieldOperand(result, object_size + kPointerSize), source); 5188 kScratchRegister);
5189 __ LoadHeapObject(rcx, original_object);
5190 __ movq(FieldOperand(result, object_size + object_offset + kPointerSize),
5191 rcx);
5177 } 5192 }
5178 5193
5179 if (has_elements) { 5194 if (has_elements) {
5180 // Copy elements backing store header. 5195 // Copy elements backing store header.
5181 __ LoadHeapObject(source, elements); 5196 __ LoadHeapObject(source, elements);
5182 for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { 5197 for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) {
5183 __ movq(rcx, FieldOperand(source, i)); 5198 __ movq(rcx, FieldOperand(source, i));
5184 __ movq(FieldOperand(result, elements_offset + i), rcx); 5199 __ movq(FieldOperand(result, elements_offset + i), rcx);
5185 } 5200 }
5186 5201
5187 // Copy elements backing store content. 5202 // Copy elements backing store content.
5188 int elements_length = elements->length(); 5203 int elements_length = elements->length();
5189 if (elements->IsFixedDoubleArray()) { 5204 if (elements->IsFixedDoubleArray()) {
5190 Handle<FixedDoubleArray> double_array = 5205 Handle<FixedDoubleArray> double_array =
5191 Handle<FixedDoubleArray>::cast(elements); 5206 Handle<FixedDoubleArray>::cast(elements);
5192 for (int i = 0; i < elements_length; i++) { 5207 for (int i = 0; i < elements_length; i++) {
5193 int64_t value = double_array->get_representation(i); 5208 int64_t value = double_array->get_representation(i);
5194 int total_offset = 5209 int total_offset =
5195 elements_offset + FixedDoubleArray::OffsetOfElementAt(i); 5210 elements_offset + FixedDoubleArray::OffsetOfElementAt(i);
5196 __ movq(rcx, value, RelocInfo::NONE64); 5211 __ movq(rcx, value, RelocInfo::NONE64);
5197 __ movq(FieldOperand(result, total_offset), rcx); 5212 __ movq(FieldOperand(result, total_offset), rcx);
5198 } 5213 }
5199 } else if (elements->IsFixedArray()) { 5214 } else if (elements->IsFixedArray()) {
5200 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); 5215 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
5216 ASSERT(original_object->HasFastObjectElements());
5217 Handle<FixedArray> original_fast_elements =
5218 Handle<FixedArray>::cast(original_elements);
5201 for (int i = 0; i < elements_length; i++) { 5219 for (int i = 0; i < elements_length; i++) {
5202 int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); 5220 int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
5203 Handle<Object> value(fast_elements->get(i)); 5221 Handle<Object> value(fast_elements->get(i));
5204 if (value->IsJSObject()) { 5222 if (value->IsJSObject()) {
5205 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 5223 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5224 Handle<JSObject> original_value_object = Handle<JSObject>::cast(
5225 Handle<Object>(original_fast_elements->get(i)));
5206 __ lea(rcx, Operand(result, *offset)); 5226 __ lea(rcx, Operand(result, *offset));
5207 __ movq(FieldOperand(result, total_offset), rcx); 5227 __ movq(FieldOperand(result, total_offset), rcx);
5208 __ LoadHeapObject(source, value_object); 5228 __ LoadHeapObject(source, value_object);
5209 EmitDeepCopy(value_object, result, source, offset, 5229 ASSERT(!value_object.is_identical_to(original_value_object));
5210 DONT_TRACK_ALLOCATION_SITE); 5230 EmitDeepCopy(value_object, original_value_object, result, source,
5231 offset, mode);
5211 } else if (value->IsHeapObject()) { 5232 } else if (value->IsHeapObject()) {
5212 __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value)); 5233 __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value));
5213 __ movq(FieldOperand(result, total_offset), rcx); 5234 __ movq(FieldOperand(result, total_offset), rcx);
5214 } else { 5235 } else {
5215 __ movq(rcx, value, RelocInfo::NONE64); 5236 __ movq(rcx, value, RelocInfo::NONE64);
5216 __ movq(FieldOperand(result, total_offset), rcx); 5237 __ movq(FieldOperand(result, total_offset), rcx);
5217 } 5238 }
5218 } 5239 }
5219 } else { 5240 } else {
5220 UNREACHABLE(); 5241 UNREACHABLE();
5221 } 5242 }
5222 } 5243 }
5223 } 5244 }
5224 5245
5225 5246
5226 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { 5247 void LCodeGen::DoFastLiteral(LFastLiteral* instr) {
5227 int size = instr->hydrogen()->total_size(); 5248 int size = instr->hydrogen()->total_size();
5228 ElementsKind boilerplate_elements_kind =
5229 instr->hydrogen()->boilerplate()->GetElementsKind();
5230
5231 // Deopt if the array literal boilerplate ElementsKind is of a type different
5232 // than the expected one. The check isn't necessary if the boilerplate has
5233 // already been converted to TERMINAL_FAST_ELEMENTS_KIND.
5234 if (CanTransitionToMoreGeneralFastElementsKind(
5235 boilerplate_elements_kind, true)) {
5236 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate());
5237 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset));
5238 // Load the map's "bit field 2".
5239 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset));
5240 // Retrieve elements_kind from bit field 2.
5241 __ and_(rcx, Immediate(Map::kElementsKindMask));
5242 __ cmpb(rcx, Immediate(boilerplate_elements_kind <<
5243 Map::kElementsKindShift));
5244 DeoptimizeIf(not_equal, instr->environment());
5245 }
5246 5249
5247 // Allocate all objects that are part of the literal in one big 5250 // Allocate all objects that are part of the literal in one big
5248 // allocation. This avoids multiple limit checks. 5251 // allocation. This avoids multiple limit checks.
5249 Label allocated, runtime_allocate; 5252 Label allocated, runtime_allocate;
5250 __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 5253 __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
5251 __ jmp(&allocated); 5254 __ jmp(&allocated);
5252 5255
5253 __ bind(&runtime_allocate); 5256 __ bind(&runtime_allocate);
5254 __ Push(Smi::FromInt(size)); 5257 __ Push(Smi::FromInt(size));
5255 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 5258 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5256 5259
5257 __ bind(&allocated); 5260 __ bind(&allocated);
5258 int offset = 0; 5261 int offset = 0;
5259 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); 5262 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate());
5260 EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset, 5263 EmitDeepCopy(instr->hydrogen()->boilerplate(),
5264 instr->hydrogen()->original_boilerplate(),
5265 rax, rbx, &offset,
5261 instr->hydrogen()->allocation_site_mode()); 5266 instr->hydrogen()->allocation_site_mode());
5262 ASSERT_EQ(size, offset); 5267 ASSERT_EQ(size, offset);
5263 } 5268 }
5264 5269
5265 5270
5266 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 5271 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
5267 Handle<FixedArray> literals(instr->environment()->closure()->literals()); 5272 Handle<FixedArray> literals(instr->environment()->closure()->literals());
5268 Handle<FixedArray> constant_properties = 5273 Handle<FixedArray> constant_properties =
5269 instr->hydrogen()->constant_properties(); 5274 instr->hydrogen()->constant_properties();
5270 5275
5271 // Set up the parameters to the stub/runtime call. 5276 // Set up the parameters to the stub/runtime call.
5272 __ PushHeapObject(literals); 5277 __ PushHeapObject(literals);
5273 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 5278 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
5274 __ Push(constant_properties); 5279 __ Push(constant_properties);
5275 int flags = instr->hydrogen()->fast_elements() 5280 int flags = instr->hydrogen()->fast_elements()
5276 ? ObjectLiteral::kFastElements 5281 ? ObjectLiteral::kFastElements
5277 : ObjectLiteral::kNoFlags; 5282 : ObjectLiteral::kNoFlags;
5278 flags |= instr->hydrogen()->has_function() 5283 flags |= instr->hydrogen()->has_function()
5279 ? ObjectLiteral::kHasFunction 5284 ? ObjectLiteral::kHasFunction
5280 : ObjectLiteral::kNoFlags; 5285 : ObjectLiteral::kNoFlags;
5286
5287 if (instr->hydrogen()->allocation_site_mode() == TRACK_ALLOCATION_SITE) {
5288 flags |= ObjectLiteral::kAllocationSiteInfoAllowed;
5289 }
5290
5281 __ Push(Smi::FromInt(flags)); 5291 __ Push(Smi::FromInt(flags));
5282 5292
5283 // Pick the right runtime function or stub to call. 5293 // Pick the right runtime function or stub to call.
5284 int properties_count = constant_properties->length() / 2; 5294 int properties_count = constant_properties->length() / 2;
5285 if (instr->hydrogen()->depth() > 1) { 5295 if (instr->hydrogen()->depth() > 1) {
5286 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); 5296 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
5287 } else if (flags != ObjectLiteral::kFastElements || 5297 } else if (flags != ObjectLiteral::kFastElements ||
5288 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 5298 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
5289 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); 5299 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
5290 } else { 5300 } else {
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
5734 FixedArray::kHeaderSize - kPointerSize)); 5744 FixedArray::kHeaderSize - kPointerSize));
5735 __ bind(&done); 5745 __ bind(&done);
5736 } 5746 }
5737 5747
5738 5748
5739 #undef __ 5749 #undef __
5740 5750
5741 } } // namespace v8::internal 5751 } } // namespace v8::internal
5742 5752
5743 #endif // V8_TARGET_ARCH_X64 5753 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698