Commit 44fd249c authored by hpayer@chromium.org's avatar hpayer@chromium.org

Refacturing BuildEmitDeepCopy.

BUG=

Review URL: https://codereview.chromium.org/15700007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14845 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent eecc9ff8
......@@ -499,8 +499,8 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
HInstruction* elements_length =
AddInstruction(new(zone) HFixedArrayBaseLength(elements));
HValue* new_elements =
BuildAllocateAndInitializeElements(context(), to_kind, elements_length);
HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
context(), to_kind, elements_length);
BuildCopyElements(context(), elements,
casted_stub()->from_kind(), new_elements,
......
......@@ -1367,9 +1367,9 @@ HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
}
void HGraphBuilder::BuildInitializeElements(HValue* elements,
ElementsKind kind,
HValue* capacity) {
void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
ElementsKind kind,
HValue* capacity) {
Factory* factory = isolate()->factory();
Handle<Map> map = IsFastDoubleElementsKind(kind)
? factory->fixed_double_array_map()
......@@ -1383,11 +1383,12 @@ void HGraphBuilder::BuildInitializeElements(HValue* elements,
}
HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context,
ElementsKind kind,
HValue* capacity) {
HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
HValue* context,
ElementsKind kind,
HValue* capacity) {
HValue* new_elements = BuildAllocateElements(context, kind, capacity);
BuildInitializeElements(new_elements, kind, capacity);
BuildInitializeElementsHeader(new_elements, kind, capacity);
return new_elements;
}
......@@ -1488,8 +1489,8 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
BuildNewSpaceArrayCheck(new_capacity, kind);
HValue* new_elements =
BuildAllocateAndInitializeElements(context, kind, new_capacity);
HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
context, kind, new_capacity);
BuildCopyElements(context, elements, kind,
new_elements, kind,
......@@ -1892,7 +1893,7 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
length_field);
// Initialize the elements
builder()->BuildInitializeElements(elements_location_, kind_, capacity);
builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
if (fill_with_hole) {
builder()->BuildFillElementsWithHole(context, elements_location_, kind_,
......@@ -9910,13 +9911,6 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
AllocationSiteMode mode) {
Zone* zone = this->zone();
HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant(
original_boilerplate_object, Representation::Tagged()));
bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE &&
boilerplate_object->map()->CanTrackAllocationSite();
// Only elements backing stores for non-COW arrays need to be copied.
Handle<FixedArrayBase> elements(boilerplate_object->elements());
Handle<FixedArrayBase> original_elements(
original_boilerplate_object->elements());
......@@ -9930,20 +9924,98 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
elements->Size() : 0;
int elements_offset = *offset + object_size;
if (create_allocation_site_info) {
elements_offset += AllocationSiteInfo::kSize;
*offset += AllocationSiteInfo::kSize;
}
*offset += object_size + elements_size;
HValue* object_elements = BuildCopyObjectHeader(boilerplate_object, target,
// Copy object elements if non-COW.
HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target,
object_offset, elements_offset, elements_size);
if (object_elements != NULL) {
BuildEmitElements(elements, original_elements, kind, object_elements,
target, offset);
}
// Copy in-object properties.
HValue* object_properties =
AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object,
object_properties, target, offset);
// Create allocation site info.
if (mode == TRACK_ALLOCATION_SITE &&
boilerplate_object->map()->CanTrackAllocationSite()) {
elements_offset += AllocationSiteInfo::kSize;
*offset += AllocationSiteInfo::kSize;
HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant(
original_boilerplate_object, Representation::Tagged()));
BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate);
}
}
HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader(
Handle<JSObject> boilerplate_object,
HInstruction* target,
int object_offset,
int elements_offset,
int elements_size) {
ASSERT(boilerplate_object->properties()->length() == 0);
Zone* zone = this->zone();
HValue* result = NULL;
HValue* object_header =
AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
Handle<Map> boilerplate_object_map(boilerplate_object->map());
AddStoreMapConstant(object_header, boilerplate_object_map);
HInstruction* elements;
if (elements_size == 0) {
Handle<Object> elements_field =
Handle<Object>(boilerplate_object->elements(), isolate());
elements = AddInstruction(new(zone) HConstant(
elements_field, Representation::Tagged()));
} else {
elements = AddInstruction(new(zone) HInnerAllocatedObject(
target, elements_offset));
result = elements;
}
AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
Handle<Object> properties_field =
Handle<Object>(boilerplate_object->properties(), isolate());
ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
HInstruction* properties = AddInstruction(new(zone) HConstant(
properties_field, Representation::None()));
HObjectAccess access = HObjectAccess::ForPropertiesPointer();
AddStore(object_header, access, properties);
if (boilerplate_object->IsJSArray()) {
Handle<JSArray> boilerplate_array =
Handle<JSArray>::cast(boilerplate_object);
Handle<Object> length_field =
Handle<Object>(boilerplate_array->length(), isolate());
HInstruction* length = AddInstruction(new(zone) HConstant(
length_field, Representation::None()));
ASSERT(boilerplate_array->length()->IsSmi());
Representation representation =
IsFastElementsKind(boilerplate_array->GetElementsKind())
? Representation::Smi() : Representation::Tagged();
AddStore(object_header, HObjectAccess::ForArrayLength(),
length, representation);
}
return result;
}
void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
Handle<JSObject> boilerplate_object,
Handle<JSObject> original_boilerplate_object,
HValue* object_properties,
HInstruction* target,
int* offset) {
Zone* zone = this->zone();
Handle<DescriptorArray> descriptors(
boilerplate_object->map()->instance_descriptors());
int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
......@@ -10006,126 +10078,97 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
AddStore(object_properties, access, value_instruction);
}
// Build Allocation Site Info if desired
if (create_allocation_site_info) {
BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate);
}
if (object_elements != NULL) {
HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant(
elements, Representation::Tagged()));
int elements_length = elements->length();
HValue* object_elements_length =
AddInstruction(new(zone) HConstant(
elements_length, Representation::Integer32()));
BuildInitializeElements(object_elements, kind, object_elements_length);
// Copy elements backing store content.
if (elements->IsFixedDoubleArray()) {
for (int i = 0; i < elements_length; i++) {
HValue* key_constant =
AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
HInstruction* value_instruction =
AddInstruction(new(zone) HLoadKeyed(
boilerplate_elements, key_constant, NULL, kind,
ALLOW_RETURN_HOLE));
HInstruction* store = AddInstruction(new(zone) HStoreKeyed(
object_elements, key_constant, value_instruction, kind));
store->ClearFlag(HValue::kDeoptimizeOnUndefined);
}
} else if (elements->IsFixedArray()) {
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
Handle<FixedArray> original_fast_elements =
Handle<FixedArray>::cast(original_elements);
for (int i = 0; i < elements_length; i++) {
Handle<Object> value(fast_elements->get(i), isolate());
HValue* key_constant =
AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
Handle<JSObject> original_value_object = Handle<JSObject>::cast(
Handle<Object>(original_fast_elements->get(i), isolate()));
HInstruction* value_instruction =
AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
AddInstruction(new(zone) HStoreKeyed(
object_elements, key_constant, value_instruction, kind));
BuildEmitDeepCopy(value_object, original_value_object, target,
offset, DONT_TRACK_ALLOCATION_SITE);
} else {
HInstruction* value_instruction =
AddInstruction(new(zone) HLoadKeyed(
boilerplate_elements, key_constant, NULL, kind,
ALLOW_RETURN_HOLE));
AddInstruction(new(zone) HStoreKeyed(
object_elements, key_constant, value_instruction, kind));
}
}
} else {
UNREACHABLE();
}
}
}
HValue* HOptimizedGraphBuilder::BuildCopyObjectHeader(
Handle<JSObject> boilerplate_object,
void HOptimizedGraphBuilder::BuildEmitElements(
Handle<FixedArrayBase> elements,
Handle<FixedArrayBase> original_elements,
ElementsKind kind,
HValue* object_elements,
HInstruction* target,
int object_offset,
int elements_offset,
int elements_size) {
ASSERT(boilerplate_object->properties()->length() == 0);
int* offset) {
Zone* zone = this->zone();
HValue* result = NULL;
HValue* object_header =
AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset));
Handle<Map> boilerplate_object_map(boilerplate_object->map());
AddStoreMapConstant(object_header, boilerplate_object_map);
int elements_length = elements->length();
HValue* object_elements_length =
AddInstruction(new(zone) HConstant(
elements_length, Representation::Integer32()));
HInstruction* elements;
if (elements_size == 0) {
Handle<Object> elements_field =
Handle<Object>(boilerplate_object->elements(), isolate());
elements = AddInstruction(new(zone) HConstant(
elements_field, Representation::Tagged()));
BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
// Copy elements backing store content.
if (elements->IsFixedDoubleArray()) {
BuildEmitFixedDoubleArray(elements, kind, object_elements);
} else if (elements->IsFixedArray()) {
BuildEmitFixedArray(elements, original_elements, kind, object_elements,
target, offset);
} else {
elements = AddInstruction(new(zone) HInnerAllocatedObject(
target, elements_offset));
result = elements;
UNREACHABLE();
}
AddStore(object_header, HObjectAccess::ForElementsPointer(), elements);
Handle<Object> properties_field =
Handle<Object>(boilerplate_object->properties(), isolate());
ASSERT(*properties_field == isolate()->heap()->empty_fixed_array());
HInstruction* properties = AddInstruction(new(zone) HConstant(
properties_field, Representation::None()));
HObjectAccess access = HObjectAccess::ForPropertiesPointer();
AddStore(object_header, access, properties);
}
if (boilerplate_object->IsJSArray()) {
Handle<JSArray> boilerplate_array =
Handle<JSArray>::cast(boilerplate_object);
Handle<Object> length_field =
Handle<Object>(boilerplate_array->length(), isolate());
HInstruction* length = AddInstruction(new(zone) HConstant(
length_field, Representation::None()));
ASSERT(boilerplate_array->length()->IsSmi());
Representation representation =
IsFastElementsKind(boilerplate_array->GetElementsKind())
? Representation::Smi() : Representation::Tagged();
AddStore(object_header, HObjectAccess::ForArrayLength(),
length, representation);
void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
Handle<FixedArrayBase> elements,
ElementsKind kind,
HValue* object_elements) {
Zone* zone = this->zone();
HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant(
elements, Representation::Tagged()));
int elements_length = elements->length();
for (int i = 0; i < elements_length; i++) {
HValue* key_constant =
AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
HInstruction* value_instruction =
AddInstruction(new(zone) HLoadKeyed(
boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE));
HInstruction* store = AddInstruction(new(zone) HStoreKeyed(
object_elements, key_constant, value_instruction, kind));
store->ClearFlag(HValue::kDeoptimizeOnUndefined);
}
}
void HOptimizedGraphBuilder::BuildEmitFixedArray(
Handle<FixedArrayBase> elements,
Handle<FixedArrayBase> original_elements,
ElementsKind kind,
HValue* object_elements,
HInstruction* target,
int* offset) {
Zone* zone = this->zone();
HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant(
elements, Representation::Tagged()));
int elements_length = elements->length();
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
Handle<FixedArray> original_fast_elements =
Handle<FixedArray>::cast(original_elements);
for (int i = 0; i < elements_length; i++) {
Handle<Object> value(fast_elements->get(i), isolate());
HValue* key_constant =
AddInstruction(new(zone) HConstant(i, Representation::Integer32()));
if (value->IsJSObject()) {
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
Handle<JSObject> original_value_object = Handle<JSObject>::cast(
Handle<Object>(original_fast_elements->get(i), isolate()));
HInstruction* value_instruction =
AddInstruction(new(zone) HInnerAllocatedObject(target, *offset));
AddInstruction(new(zone) HStoreKeyed(
object_elements, key_constant, value_instruction, kind));
BuildEmitDeepCopy(value_object, original_value_object, target,
offset, DONT_TRACK_ALLOCATION_SITE);
} else {
HInstruction* value_instruction =
AddInstruction(new(zone) HLoadKeyed(
boilerplate_elements, key_constant, NULL, kind,
ALLOW_RETURN_HOLE));
AddInstruction(new(zone) HStoreKeyed(
object_elements, key_constant, value_instruction, kind));
}
}
return result;
}
void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL);
......
......@@ -1275,13 +1275,13 @@ class HGraphBuilder {
ElementsKind kind,
HValue* capacity);
void BuildInitializeElements(HValue* elements,
ElementsKind kind,
HValue* capacity);
void BuildInitializeElementsHeader(HValue* elements,
ElementsKind kind,
HValue* capacity);
HValue* BuildAllocateAndInitializeElements(HValue* context,
ElementsKind kind,
HValue* capacity);
HValue* BuildAllocateElementsAndInitializeElementsHeader(HValue* context,
ElementsKind kind,
HValue* capacity);
// array must have been allocated with enough room for
// 1) the JSArray, 2) a AllocationSiteInfo if mode requires it,
......@@ -1738,13 +1738,37 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
int* offset,
AllocationSiteMode mode);
MUST_USE_RESULT HValue* BuildCopyObjectHeader(
MUST_USE_RESULT HValue* BuildEmitObjectHeader(
Handle<JSObject> boilerplat_object,
HInstruction* target,
int object_offset,
int elements_offset,
int elements_size);
void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
Handle<JSObject> original_boilerplate_object,
HValue* object_properties,
HInstruction* target,
int* offset);
void BuildEmitElements(Handle<FixedArrayBase> elements,
Handle<FixedArrayBase> original_elements,
ElementsKind kind,
HValue* object_elements,
HInstruction* target,
int* offset);
void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
ElementsKind kind,
HValue* object_elements);
void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
Handle<FixedArrayBase> original_elements,
ElementsKind kind,
HValue* object_elements,
HInstruction* target,
int* offset);
void AddCheckPrototypeMaps(Handle<JSObject> holder,
Handle<Map> receiver_map);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment