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

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: Now with ports to arm and x64 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 4899 matching lines...) Expand 10 before | Expand all | Expand 10 after
4910 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 4910 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
4911 // Load the map's "bit field 2". 4911 // Load the map's "bit field 2".
4912 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); 4912 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset));
4913 // Retrieve elements_kind from bit field 2. 4913 // Retrieve elements_kind from bit field 2.
4914 __ and_(rbx, Immediate(Map::kElementsKindMask)); 4914 __ and_(rbx, Immediate(Map::kElementsKindMask));
4915 __ cmpb(rbx, Immediate(boilerplate_elements_kind << 4915 __ cmpb(rbx, Immediate(boilerplate_elements_kind <<
4916 Map::kElementsKindShift)); 4916 Map::kElementsKindShift));
4917 DeoptimizeIf(not_equal, instr->environment()); 4917 DeoptimizeIf(not_equal, instr->environment());
4918 } 4918 }
4919 4919
4920 int flags = allocation_site_mode == TRACK_ALLOCATION_SITE
4921 ? ArrayLiteral::kAllocationSiteInfoAllowed
4922 : ArrayLiteral::kNoFlags;
4923
4920 // Set up the parameters to the stub/runtime call. 4924 // Set up the parameters to the stub/runtime call.
4921 __ PushHeapObject(literals); 4925 __ PushHeapObject(literals);
4922 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 4926 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
4923 // Boilerplate already exists, constant elements are never accessed. 4927 // Boilerplate already exists, constant elements are never accessed.
4924 // Pass an empty fixed array. 4928 // Pass an empty fixed array.
4925 __ Push(isolate()->factory()->empty_fixed_array()); 4929 __ Push(isolate()->factory()->empty_fixed_array());
4930 __ Push(Smi::FromInt(flags));
4926 4931
4927 // Pick the right runtime function or stub to call. 4932 // Pick the right runtime function or stub to call.
4928 int length = instr->hydrogen()->length(); 4933 int length = instr->hydrogen()->length();
4929 if (instr->hydrogen()->IsCopyOnWrite()) { 4934 if (instr->hydrogen()->IsCopyOnWrite()) {
4930 ASSERT(instr->hydrogen()->depth() == 1); 4935 ASSERT(instr->hydrogen()->depth() == 1);
4931 FastCloneShallowArrayStub::Mode mode = 4936 FastCloneShallowArrayStub::Mode mode =
4932 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS; 4937 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS;
4933 FastCloneShallowArrayStub stub(mode, DONT_TRACK_ALLOCATION_SITE, length); 4938 FastCloneShallowArrayStub stub(mode, DONT_TRACK_ALLOCATION_SITE, length);
4934 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4939 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4935 } else if (instr->hydrogen()->depth() > 1) { 4940 } else if (instr->hydrogen()->depth() > 1) {
4936 CallRuntime(Runtime::kCreateArrayLiteral, 3, instr); 4941 CallRuntime(Runtime::kCreateArrayLiteral, 4, instr);
4937 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 4942 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
4938 CallRuntime(Runtime::kCreateArrayLiteralShallow, 3, instr); 4943 CallRuntime(Runtime::kCreateArrayLiteralShallow, 4, instr);
4939 } else { 4944 } else {
4940 FastCloneShallowArrayStub::Mode mode = 4945 FastCloneShallowArrayStub::Mode mode =
4941 boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS 4946 boilerplate_elements_kind == FAST_DOUBLE_ELEMENTS
4942 ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS 4947 ? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
4943 : FastCloneShallowArrayStub::CLONE_ELEMENTS; 4948 : FastCloneShallowArrayStub::CLONE_ELEMENTS;
4944 FastCloneShallowArrayStub stub(mode, allocation_site_mode, length); 4949 FastCloneShallowArrayStub stub(mode, allocation_site_mode, length);
4945 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4950 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4946 } 4951 }
4947 } 4952 }
4948 4953
4949 4954
4950 void LCodeGen::EmitDeepCopy(Handle<JSObject> object, 4955 void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
4956 Handle<JSObject> original_object,
4951 Register result, 4957 Register result,
4952 Register source, 4958 Register source,
4953 int* offset, 4959 int* offset,
4954 AllocationSiteMode mode) { 4960 AllocationSiteMode mode) {
4955 ASSERT(!source.is(rcx)); 4961 ASSERT(!source.is(rcx));
4956 ASSERT(!result.is(rcx)); 4962 ASSERT(!result.is(rcx));
4957 4963
4964 // Should we track allocation info for *this* object in the tree?
4958 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && 4965 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
4959 object->map()->CanTrackAllocationSite(); 4966 object->map()->CanTrackAllocationSite();
4960 4967
4968 if (create_allocation_site_info && object->IsJSArray()) {
4969 create_allocation_site_info = AllocationSiteInfo::GetMode(
4970 object->GetElementsKind()) == TRACK_ALLOCATION_SITE;
4971 }
4972
4961 // Only elements backing stores for non-COW arrays need to be copied. 4973 // Only elements backing stores for non-COW arrays need to be copied.
4962 Handle<FixedArrayBase> elements(object->elements()); 4974 Handle<FixedArrayBase> elements(object->elements());
4975 Handle<FixedArrayBase> original_elements(original_object->elements());
4963 bool has_elements = elements->length() > 0 && 4976 bool has_elements = elements->length() > 0 &&
4964 elements->map() != isolate()->heap()->fixed_cow_array_map(); 4977 elements->map() != isolate()->heap()->fixed_cow_array_map();
4965 4978
4966 // Increase the offset so that subsequent objects end up right after 4979 // Increase the offset so that subsequent objects end up right after
4967 // this object and its backing store. 4980 // this object and its backing store.
4968 int object_offset = *offset; 4981 int object_offset = *offset;
4969 int object_size = object->map()->instance_size(); 4982 int object_size = object->map()->instance_size();
4970 int elements_size = has_elements ? elements->Size() : 0; 4983 int elements_size = has_elements ? elements->Size() : 0;
4971 int elements_offset = *offset + object_size; 4984 int elements_offset = *offset + object_size;
4972 if (create_allocation_site_info) { 4985 if (create_allocation_site_info) {
(...skipping 15 matching lines...) Expand all
4988 } 5001 }
4989 __ movq(FieldOperand(result, object_offset + i), rcx); 5002 __ movq(FieldOperand(result, object_offset + i), rcx);
4990 } 5003 }
4991 5004
4992 // Copy in-object properties. 5005 // Copy in-object properties.
4993 for (int i = 0; i < inobject_properties; i++) { 5006 for (int i = 0; i < inobject_properties; i++) {
4994 int total_offset = object_offset + object->GetInObjectPropertyOffset(i); 5007 int total_offset = object_offset + object->GetInObjectPropertyOffset(i);
4995 Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i)); 5008 Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i));
4996 if (value->IsJSObject()) { 5009 if (value->IsJSObject()) {
4997 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 5010 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5011 Handle<JSObject> original_value_object = Handle<JSObject>::cast(
5012 Handle<Object>(original_object->InObjectPropertyAt(i)));
5013
4998 __ lea(rcx, Operand(result, *offset)); 5014 __ lea(rcx, Operand(result, *offset));
4999 __ movq(FieldOperand(result, total_offset), rcx); 5015 __ movq(FieldOperand(result, total_offset), rcx);
5000 __ LoadHeapObject(source, value_object); 5016 __ LoadHeapObject(source, value_object);
5001 EmitDeepCopy(value_object, result, source, offset, 5017 EmitDeepCopy(value_object, original_value_object, result, source,
5002 DONT_TRACK_ALLOCATION_SITE); 5018 offset, mode);
5003 } else if (value->IsHeapObject()) { 5019 } else if (value->IsHeapObject()) {
5004 __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value)); 5020 __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value));
5005 __ movq(FieldOperand(result, total_offset), rcx); 5021 __ movq(FieldOperand(result, total_offset), rcx);
5006 } else { 5022 } else {
5007 __ movq(rcx, value, RelocInfo::NONE64); 5023 __ movq(rcx, value, RelocInfo::NONE64);
5008 __ movq(FieldOperand(result, total_offset), rcx); 5024 __ movq(FieldOperand(result, total_offset), rcx);
5009 } 5025 }
5010 } 5026 }
5011 5027
5012 // Build Allocation Site Info if desired 5028 // Build Allocation Site Info if desired
5013 if (create_allocation_site_info) { 5029 if (create_allocation_site_info) {
5014 __ LoadRoot(kScratchRegister, Heap::kAllocationSiteInfoMapRootIndex); 5030 __ LoadRoot(kScratchRegister, Heap::kAllocationSiteInfoMapRootIndex);
5015 __ movq(FieldOperand(result, object_size), kScratchRegister); 5031 __ movq(FieldOperand(result, object_size + object_offset), kScratchRegister) ;
5016 __ movq(FieldOperand(result, object_size + kPointerSize), source); 5032 __ LoadHeapObject(rcx, original_object);
5033 __ movq(FieldOperand(result, object_size + object_offset + kPointerSize),
5034 rcx);
5017 } 5035 }
5018 5036
5019 if (has_elements) { 5037 if (has_elements) {
5020 // Copy elements backing store header. 5038 // Copy elements backing store header.
5021 __ LoadHeapObject(source, elements); 5039 __ LoadHeapObject(source, elements);
5022 for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { 5040 for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) {
5023 __ movq(rcx, FieldOperand(source, i)); 5041 __ movq(rcx, FieldOperand(source, i));
5024 __ movq(FieldOperand(result, elements_offset + i), rcx); 5042 __ movq(FieldOperand(result, elements_offset + i), rcx);
5025 } 5043 }
5026 5044
5027 // Copy elements backing store content. 5045 // Copy elements backing store content.
5028 int elements_length = elements->length(); 5046 int elements_length = elements->length();
5029 if (elements->IsFixedDoubleArray()) { 5047 if (elements->IsFixedDoubleArray()) {
5030 Handle<FixedDoubleArray> double_array = 5048 Handle<FixedDoubleArray> double_array =
5031 Handle<FixedDoubleArray>::cast(elements); 5049 Handle<FixedDoubleArray>::cast(elements);
5032 for (int i = 0; i < elements_length; i++) { 5050 for (int i = 0; i < elements_length; i++) {
5033 int64_t value = double_array->get_representation(i); 5051 int64_t value = double_array->get_representation(i);
5034 int total_offset = 5052 int total_offset =
5035 elements_offset + FixedDoubleArray::OffsetOfElementAt(i); 5053 elements_offset + FixedDoubleArray::OffsetOfElementAt(i);
5036 __ movq(rcx, value, RelocInfo::NONE64); 5054 __ movq(rcx, value, RelocInfo::NONE64);
5037 __ movq(FieldOperand(result, total_offset), rcx); 5055 __ movq(FieldOperand(result, total_offset), rcx);
5038 } 5056 }
5039 } else if (elements->IsFixedArray()) { 5057 } else if (elements->IsFixedArray()) {
5040 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); 5058 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
5059 Handle<FixedArray> original_fast_elements =
5060 Handle<FixedArray>::cast(original_elements);
5041 for (int i = 0; i < elements_length; i++) { 5061 for (int i = 0; i < elements_length; i++) {
5042 int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i); 5062 int total_offset = elements_offset + FixedArray::OffsetOfElementAt(i);
5043 Handle<Object> value(fast_elements->get(i)); 5063 Handle<Object> value(fast_elements->get(i));
5044 if (value->IsJSObject()) { 5064 if (value->IsJSObject()) {
5045 Handle<JSObject> value_object = Handle<JSObject>::cast(value); 5065 Handle<JSObject> value_object = Handle<JSObject>::cast(value);
5066 Handle<JSObject> original_value_object = Handle<JSObject>::cast(
5067 Handle<Object>(original_fast_elements->get(i)));
5046 __ lea(rcx, Operand(result, *offset)); 5068 __ lea(rcx, Operand(result, *offset));
5047 __ movq(FieldOperand(result, total_offset), rcx); 5069 __ movq(FieldOperand(result, total_offset), rcx);
5048 __ LoadHeapObject(source, value_object); 5070 __ LoadHeapObject(source, value_object);
5049 EmitDeepCopy(value_object, result, source, offset, 5071
5050 DONT_TRACK_ALLOCATION_SITE); 5072 // TODO(mvstanton): do we have to worry that the original object
5073 // changed from a fixed array to a fixeddoublearray? If that happened
5074 // then the original_value_object expression might point to garbage
5075 // memory, right?
5076 ASSERT(!value_object.is_identical_to(original_value_object));
5077 EmitDeepCopy(value_object, original_value_object, result, source,
5078 offset, mode);
5051 } else if (value->IsHeapObject()) { 5079 } else if (value->IsHeapObject()) {
5052 __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value)); 5080 __ LoadHeapObject(rcx, Handle<HeapObject>::cast(value));
5053 __ movq(FieldOperand(result, total_offset), rcx); 5081 __ movq(FieldOperand(result, total_offset), rcx);
5054 } else { 5082 } else {
5055 __ movq(rcx, value, RelocInfo::NONE64); 5083 __ movq(rcx, value, RelocInfo::NONE64);
5056 __ movq(FieldOperand(result, total_offset), rcx); 5084 __ movq(FieldOperand(result, total_offset), rcx);
5057 } 5085 }
5058 } 5086 }
5059 } else { 5087 } else {
5060 UNREACHABLE(); 5088 UNREACHABLE();
5061 } 5089 }
5062 } 5090 }
5063 } 5091 }
5064 5092
5065 5093
5066 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { 5094 void LCodeGen::DoFastLiteral(LFastLiteral* instr) {
5067 int size = instr->hydrogen()->total_size(); 5095 int size = instr->hydrogen()->total_size();
5068 ElementsKind boilerplate_elements_kind =
5069 instr->hydrogen()->boilerplate()->GetElementsKind();
5070
5071 // Deopt if the array literal boilerplate ElementsKind is of a type different
5072 // than the expected one. The check isn't necessary if the boilerplate has
5073 // already been converted to TERMINAL_FAST_ELEMENTS_KIND.
5074 if (CanTransitionToMoreGeneralFastElementsKind(
5075 boilerplate_elements_kind, true)) {
5076 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate());
5077 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset));
5078 // Load the map's "bit field 2".
5079 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset));
5080 // Retrieve elements_kind from bit field 2.
5081 __ and_(rcx, Immediate(Map::kElementsKindMask));
5082 __ cmpb(rcx, Immediate(boilerplate_elements_kind <<
5083 Map::kElementsKindShift));
5084 DeoptimizeIf(not_equal, instr->environment());
5085 }
5086 5096
5087 // Allocate all objects that are part of the literal in one big 5097 // Allocate all objects that are part of the literal in one big
5088 // allocation. This avoids multiple limit checks. 5098 // allocation. This avoids multiple limit checks.
5089 Label allocated, runtime_allocate; 5099 Label allocated, runtime_allocate;
5090 __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 5100 __ AllocateInNewSpace(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT);
5091 __ jmp(&allocated); 5101 __ jmp(&allocated);
5092 5102
5093 __ bind(&runtime_allocate); 5103 __ bind(&runtime_allocate);
5094 __ Push(Smi::FromInt(size)); 5104 __ Push(Smi::FromInt(size));
5095 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); 5105 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5096 5106
5097 __ bind(&allocated); 5107 __ bind(&allocated);
5098 int offset = 0; 5108 int offset = 0;
5099 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); 5109 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate());
5100 EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset, 5110 EmitDeepCopy(instr->hydrogen()->boilerplate(),
5111 instr->hydrogen()->original_boilerplate(),
5112 rax, rbx, &offset,
5101 instr->hydrogen()->allocation_site_mode()); 5113 instr->hydrogen()->allocation_site_mode());
5102 ASSERT_EQ(size, offset); 5114 ASSERT_EQ(size, offset);
5103 } 5115 }
5104 5116
5105 5117
5106 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) { 5118 void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
5107 Handle<FixedArray> literals(instr->environment()->closure()->literals()); 5119 Handle<FixedArray> literals(instr->environment()->closure()->literals());
5108 Handle<FixedArray> constant_properties = 5120 Handle<FixedArray> constant_properties =
5109 instr->hydrogen()->constant_properties(); 5121 instr->hydrogen()->constant_properties();
5110 5122
5111 // Set up the parameters to the stub/runtime call. 5123 // Set up the parameters to the stub/runtime call.
5112 __ PushHeapObject(literals); 5124 __ PushHeapObject(literals);
5113 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); 5125 __ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
5114 __ Push(constant_properties); 5126 __ Push(constant_properties);
5115 int flags = instr->hydrogen()->fast_elements() 5127 int flags = instr->hydrogen()->fast_elements()
5116 ? ObjectLiteral::kFastElements 5128 ? ObjectLiteral::kFastElements
5117 : ObjectLiteral::kNoFlags; 5129 : ObjectLiteral::kNoFlags;
5118 flags |= instr->hydrogen()->has_function() 5130 flags |= instr->hydrogen()->has_function()
5119 ? ObjectLiteral::kHasFunction 5131 ? ObjectLiteral::kHasFunction
5120 : ObjectLiteral::kNoFlags; 5132 : ObjectLiteral::kNoFlags;
5133
5134 if (instr->hydrogen()->allocation_site_mode() == TRACK_ALLOCATION_SITE) {
5135 flags |= ObjectLiteral::kAllocationSiteInfoAllowed;
5136 }
5137
5121 __ Push(Smi::FromInt(flags)); 5138 __ Push(Smi::FromInt(flags));
5122 5139
5123 // Pick the right runtime function or stub to call. 5140 // Pick the right runtime function or stub to call.
5124 int properties_count = constant_properties->length() / 2; 5141 int properties_count = constant_properties->length() / 2;
5125 if (instr->hydrogen()->depth() > 1) { 5142 if (instr->hydrogen()->depth() > 1) {
5126 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr); 5143 CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
5127 } else if (flags != ObjectLiteral::kFastElements || 5144 } else if (flags != ObjectLiteral::kFastElements ||
5128 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 5145 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
5129 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr); 5146 CallRuntime(Runtime::kCreateObjectLiteralShallow, 4, instr);
5130 } else { 5147 } else {
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
5574 FixedArray::kHeaderSize - kPointerSize)); 5591 FixedArray::kHeaderSize - kPointerSize));
5575 __ bind(&done); 5592 __ bind(&done);
5576 } 5593 }
5577 5594
5578 5595
5579 #undef __ 5596 #undef __
5580 5597
5581 } } // namespace v8::internal 5598 } } // namespace v8::internal
5582 5599
5583 #endif // V8_TARGET_ARCH_X64 5600 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698