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() { ...@@ -499,8 +499,8 @@ HValue* CodeStubGraphBuilder<TransitionElementsKindStub>::BuildCodeStub() {
HInstruction* elements_length = HInstruction* elements_length =
AddInstruction(new(zone) HFixedArrayBaseLength(elements)); AddInstruction(new(zone) HFixedArrayBaseLength(elements));
HValue* new_elements = HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
BuildAllocateAndInitializeElements(context(), to_kind, elements_length); context(), to_kind, elements_length);
BuildCopyElements(context(), elements, BuildCopyElements(context(), elements,
casted_stub()->from_kind(), new_elements, casted_stub()->from_kind(), new_elements,
......
...@@ -1367,9 +1367,9 @@ HValue* HGraphBuilder::BuildAllocateElements(HValue* context, ...@@ -1367,9 +1367,9 @@ HValue* HGraphBuilder::BuildAllocateElements(HValue* context,
} }
void HGraphBuilder::BuildInitializeElements(HValue* elements, void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
ElementsKind kind, ElementsKind kind,
HValue* capacity) { HValue* capacity) {
Factory* factory = isolate()->factory(); Factory* factory = isolate()->factory();
Handle<Map> map = IsFastDoubleElementsKind(kind) Handle<Map> map = IsFastDoubleElementsKind(kind)
? factory->fixed_double_array_map() ? factory->fixed_double_array_map()
...@@ -1383,11 +1383,12 @@ void HGraphBuilder::BuildInitializeElements(HValue* elements, ...@@ -1383,11 +1383,12 @@ void HGraphBuilder::BuildInitializeElements(HValue* elements,
} }
HValue* HGraphBuilder::BuildAllocateAndInitializeElements(HValue* context, HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
ElementsKind kind, HValue* context,
HValue* capacity) { ElementsKind kind,
HValue* capacity) {
HValue* new_elements = BuildAllocateElements(context, kind, capacity); HValue* new_elements = BuildAllocateElements(context, kind, capacity);
BuildInitializeElements(new_elements, kind, capacity); BuildInitializeElementsHeader(new_elements, kind, capacity);
return new_elements; return new_elements;
} }
...@@ -1488,8 +1489,8 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object, ...@@ -1488,8 +1489,8 @@ HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
BuildNewSpaceArrayCheck(new_capacity, kind); BuildNewSpaceArrayCheck(new_capacity, kind);
HValue* new_elements = HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
BuildAllocateAndInitializeElements(context, kind, new_capacity); context, kind, new_capacity);
BuildCopyElements(context, elements, kind, BuildCopyElements(context, elements, kind,
new_elements, kind, new_elements, kind,
...@@ -1892,7 +1893,7 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes, ...@@ -1892,7 +1893,7 @@ HValue* HGraphBuilder::JSArrayBuilder::AllocateArray(HValue* size_in_bytes,
length_field); length_field);
// Initialize the elements // Initialize the elements
builder()->BuildInitializeElements(elements_location_, kind_, capacity); builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
if (fill_with_hole) { if (fill_with_hole) {
builder()->BuildFillElementsWithHole(context, elements_location_, kind_, builder()->BuildFillElementsWithHole(context, elements_location_, kind_,
...@@ -9910,13 +9911,6 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy( ...@@ -9910,13 +9911,6 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
AllocationSiteMode mode) { AllocationSiteMode mode) {
Zone* zone = this->zone(); 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> elements(boilerplate_object->elements());
Handle<FixedArrayBase> original_elements( Handle<FixedArrayBase> original_elements(
original_boilerplate_object->elements()); original_boilerplate_object->elements());
...@@ -9930,20 +9924,98 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy( ...@@ -9930,20 +9924,98 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
elements->map() != isolate()->heap()->fixed_cow_array_map()) ? elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
elements->Size() : 0; elements->Size() : 0;
int elements_offset = *offset + object_size; int elements_offset = *offset + object_size;
if (create_allocation_site_info) {
elements_offset += AllocationSiteInfo::kSize;
*offset += AllocationSiteInfo::kSize;
}
*offset += object_size + elements_size; *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); object_offset, elements_offset, elements_size);
if (object_elements != NULL) {
BuildEmitElements(elements, original_elements, kind, object_elements,
target, offset);
}
// Copy in-object properties. // Copy in-object properties.
HValue* object_properties = HValue* object_properties =
AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); 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( Handle<DescriptorArray> descriptors(
boilerplate_object->map()->instance_descriptors()); boilerplate_object->map()->instance_descriptors());
int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
...@@ -10006,126 +10078,97 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy( ...@@ -10006,126 +10078,97 @@ void HOptimizedGraphBuilder::BuildEmitDeepCopy(
HObjectAccess access = HObjectAccess::ForJSObjectOffset(i); HObjectAccess access = HObjectAccess::ForJSObjectOffset(i);
AddStore(object_properties, access, value_instruction); 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( void HOptimizedGraphBuilder::BuildEmitElements(
Handle<JSObject> boilerplate_object, Handle<FixedArrayBase> elements,
Handle<FixedArrayBase> original_elements,
ElementsKind kind,
HValue* object_elements,
HInstruction* target, HInstruction* target,
int object_offset, int* offset) {
int elements_offset,
int elements_size) {
ASSERT(boilerplate_object->properties()->length() == 0);
Zone* zone = this->zone(); Zone* zone = this->zone();
HValue* result = NULL;
HValue* object_header = int elements_length = elements->length();
AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); HValue* object_elements_length =
Handle<Map> boilerplate_object_map(boilerplate_object->map()); AddInstruction(new(zone) HConstant(
AddStoreMapConstant(object_header, boilerplate_object_map); elements_length, Representation::Integer32()));
HInstruction* elements; BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
if (elements_size == 0) {
Handle<Object> elements_field = // Copy elements backing store content.
Handle<Object>(boilerplate_object->elements(), isolate()); if (elements->IsFixedDoubleArray()) {
elements = AddInstruction(new(zone) HConstant( BuildEmitFixedDoubleArray(elements, kind, object_elements);
elements_field, Representation::Tagged())); } else if (elements->IsFixedArray()) {
BuildEmitFixedArray(elements, original_elements, kind, object_elements,
target, offset);
} else { } else {
elements = AddInstruction(new(zone) HInnerAllocatedObject( UNREACHABLE();
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()); void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
Representation representation = Handle<FixedArrayBase> elements,
IsFastElementsKind(boilerplate_array->GetElementsKind()) ElementsKind kind,
? Representation::Smi() : Representation::Tagged(); HValue* object_elements) {
AddStore(object_header, HObjectAccess::ForArrayLength(), Zone* zone = this->zone();
length, representation); 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) { void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
ASSERT(!HasStackOverflow()); ASSERT(!HasStackOverflow());
ASSERT(current_block() != NULL); ASSERT(current_block() != NULL);
......
...@@ -1275,13 +1275,13 @@ class HGraphBuilder { ...@@ -1275,13 +1275,13 @@ class HGraphBuilder {
ElementsKind kind, ElementsKind kind,
HValue* capacity); HValue* capacity);
void BuildInitializeElements(HValue* elements, void BuildInitializeElementsHeader(HValue* elements,
ElementsKind kind, ElementsKind kind,
HValue* capacity); HValue* capacity);
HValue* BuildAllocateAndInitializeElements(HValue* context, HValue* BuildAllocateElementsAndInitializeElementsHeader(HValue* context,
ElementsKind kind, ElementsKind kind,
HValue* capacity); HValue* capacity);
// array must have been allocated with enough room for // array must have been allocated with enough room for
// 1) the JSArray, 2) a AllocationSiteInfo if mode requires it, // 1) the JSArray, 2) a AllocationSiteInfo if mode requires it,
...@@ -1738,13 +1738,37 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor { ...@@ -1738,13 +1738,37 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor {
int* offset, int* offset,
AllocationSiteMode mode); AllocationSiteMode mode);
MUST_USE_RESULT HValue* BuildCopyObjectHeader( MUST_USE_RESULT HValue* BuildEmitObjectHeader(
Handle<JSObject> boilerplat_object, Handle<JSObject> boilerplat_object,
HInstruction* target, HInstruction* target,
int object_offset, int object_offset,
int elements_offset, int elements_offset,
int elements_size); 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, void AddCheckPrototypeMaps(Handle<JSObject> holder,
Handle<Map> receiver_map); 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