OLD | NEW |
---|---|
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 6022 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6033 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 6033 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
6034 ASSERT(!HasStackOverflow()); | 6034 ASSERT(!HasStackOverflow()); |
6035 ASSERT(current_block() != NULL); | 6035 ASSERT(current_block() != NULL); |
6036 ASSERT(current_block()->HasPredecessor()); | 6036 ASSERT(current_block()->HasPredecessor()); |
6037 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 6037 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
6038 HValue* context = environment()->LookupContext(); | 6038 HValue* context = environment()->LookupContext(); |
6039 HInstruction* literal; | 6039 HInstruction* literal; |
6040 | 6040 |
6041 // Check whether to use fast or slow deep-copying for boilerplate. | 6041 // Check whether to use fast or slow deep-copying for boilerplate. |
6042 int total_size = 0; | 6042 int total_size = 0; |
6043 int max_properties = HFastLiteral::kMaxLiteralProperties; | 6043 int max_properties = kMaxLiteralProperties; |
6044 Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()), | 6044 Handle<Object> boilerplate(closure->literals()->get(expr->literal_index()), |
6045 isolate()); | 6045 isolate()); |
6046 if (boilerplate->IsJSObject() && | 6046 if (boilerplate->IsJSObject() && |
6047 IsFastLiteral(Handle<JSObject>::cast(boilerplate), | 6047 IsFastLiteral(Handle<JSObject>::cast(boilerplate), |
6048 HFastLiteral::kMaxLiteralDepth, | 6048 kMaxLiteralDepth, |
6049 &max_properties, | 6049 &max_properties, |
6050 &total_size)) { | 6050 &total_size)) { |
6051 Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); | 6051 Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); |
6052 literal = new(zone()) HFastLiteral(context, | 6052 literal = BuildFastLiteral(context, |
6053 boilerplate_object, | 6053 boilerplate_object, |
6054 total_size, | 6054 total_size, |
6055 expr->literal_index(), | 6055 DONT_TRACK_ALLOCATION_SITE, |
6056 expr->depth(), | 6056 environment()->previous_ast_id()); |
6057 DONT_TRACK_ALLOCATION_SITE); | |
6058 } else { | 6057 } else { |
6059 literal = new(zone()) HObjectLiteral(context, | 6058 literal = AddInstruction( |
6060 expr->constant_properties(), | 6059 new(zone()) HObjectLiteral(context, |
6061 expr->fast_elements(), | 6060 expr->constant_properties(), |
6062 expr->literal_index(), | 6061 expr->fast_elements(), |
6063 expr->depth(), | 6062 expr->literal_index(), |
6064 expr->has_function()); | 6063 expr->depth(), |
6064 expr->has_function())); | |
6065 } | 6065 } |
6066 | 6066 |
6067 // The object is expected in the bailout environment during computation | 6067 // The object is expected in the bailout environment during computation |
6068 // of the property values and is the value of the entire expression. | 6068 // of the property values and is the value of the entire expression. |
6069 PushAndAdd(literal); | 6069 Push(literal); |
6070 | 6070 |
6071 expr->CalculateEmitStore(zone()); | 6071 expr->CalculateEmitStore(zone()); |
6072 | 6072 |
6073 for (int i = 0; i < expr->properties()->length(); i++) { | 6073 for (int i = 0; i < expr->properties()->length(); i++) { |
6074 ObjectLiteral::Property* property = expr->properties()->at(i); | 6074 ObjectLiteral::Property* property = expr->properties()->at(i); |
6075 if (property->IsCompileTimeValue()) continue; | 6075 if (property->IsCompileTimeValue()) continue; |
6076 | 6076 |
6077 Literal* key = property->key(); | 6077 Literal* key = property->key(); |
6078 Expression* value = property->value(); | 6078 Expression* value = property->value(); |
6079 | 6079 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6168 Handle<JSObject>::cast(boilerplate)->GetElementsKind(); | 6168 Handle<JSObject>::cast(boilerplate)->GetElementsKind(); |
6169 | 6169 |
6170 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 6170 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
6171 // end, we want to quit creating allocation site info after a certain number | 6171 // end, we want to quit creating allocation site info after a certain number |
6172 // of GCs for a call site. | 6172 // of GCs for a call site. |
6173 AllocationSiteMode mode = AllocationSiteInfo::GetMode( | 6173 AllocationSiteMode mode = AllocationSiteInfo::GetMode( |
6174 boilerplate_elements_kind); | 6174 boilerplate_elements_kind); |
6175 | 6175 |
6176 // Check whether to use fast or slow deep-copying for boilerplate. | 6176 // Check whether to use fast or slow deep-copying for boilerplate. |
6177 int total_size = 0; | 6177 int total_size = 0; |
6178 int max_properties = HFastLiteral::kMaxLiteralProperties; | 6178 int max_properties = kMaxLiteralProperties; |
6179 if (IsFastLiteral(boilerplate, | 6179 if (IsFastLiteral(boilerplate, |
6180 HFastLiteral::kMaxLiteralDepth, | 6180 kMaxLiteralDepth, |
6181 &max_properties, | 6181 &max_properties, |
6182 &total_size)) { | 6182 &total_size)) { |
6183 if (mode == TRACK_ALLOCATION_SITE) { | 6183 if (mode == TRACK_ALLOCATION_SITE) { |
6184 total_size += AllocationSiteInfo::kSize; | 6184 total_size += AllocationSiteInfo::kSize; |
6185 } | 6185 } |
6186 literal = new(zone()) HFastLiteral(context, | 6186 literal = BuildFastLiteral(context, |
6187 boilerplate, | 6187 boilerplate, |
6188 total_size, | 6188 total_size, |
6189 expr->literal_index(), | 6189 mode, |
6190 expr->depth(), | 6190 environment()->previous_ast_id()); |
6191 mode); | |
6192 } else { | 6191 } else { |
6193 literal = new(zone()) HArrayLiteral(context, | 6192 literal = AddInstruction( |
6194 boilerplate, | 6193 new(zone()) HArrayLiteral(context, |
6195 length, | 6194 boilerplate, |
6196 expr->literal_index(), | 6195 length, |
6197 expr->depth(), | 6196 expr->literal_index(), |
6198 mode); | 6197 expr->depth(), |
6198 mode)); | |
6199 } | 6199 } |
6200 | 6200 |
6201 // The array is expected in the bailout environment during computation | 6201 // The array is expected in the bailout environment during computation |
6202 // of the property values and is the value of the entire expression. | 6202 // of the property values and is the value of the entire expression. |
6203 PushAndAdd(literal); | 6203 Push(literal); |
6204 | 6204 |
6205 HLoadElements* elements = NULL; | 6205 HLoadElements* elements = NULL; |
6206 | 6206 |
6207 for (int i = 0; i < length; i++) { | 6207 for (int i = 0; i < length; i++) { |
6208 Expression* subexpr = subexprs->at(i); | 6208 Expression* subexpr = subexprs->at(i); |
6209 // If the subexpression is a literal or a simple materialized literal it | 6209 // If the subexpression is a literal or a simple materialized literal it |
6210 // is already set in the cloned array. | 6210 // is already set in the cloned array. |
6211 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 6211 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
6212 | 6212 |
6213 CHECK_ALIVE(VisitForValue(subexpr)); | 6213 CHECK_ALIVE(VisitForValue(subexpr)); |
(...skipping 3676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9890 if (function_state()->outer() != NULL) { | 9890 if (function_state()->outer() != NULL) { |
9891 return new(zone()) HConstant( | 9891 return new(zone()) HConstant( |
9892 function_state()->compilation_info()->closure(), | 9892 function_state()->compilation_info()->closure(), |
9893 Representation::Tagged()); | 9893 Representation::Tagged()); |
9894 } else { | 9894 } else { |
9895 return new(zone()) HThisFunction; | 9895 return new(zone()) HThisFunction; |
9896 } | 9896 } |
9897 } | 9897 } |
9898 | 9898 |
9899 | 9899 |
9900 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | |
9901 HValue* context, | |
9902 Handle<JSObject> boilerplate_object, | |
9903 int size, | |
9904 AllocationSiteMode mode, | |
9905 BailoutId id) { | |
9906 Zone* zone = this->zone(); | |
9907 Handle<Map> map(boilerplate_object->map()); | |
9908 ElementsKind kind = map->elements_kind(); | |
9909 bool packed = IsFastPackedElementsKind(kind); | |
9910 | |
9911 HInstruction* boilerplate = AddInstruction(new(zone) HConstant( | |
9912 boilerplate_object, Representation::Tagged())); | |
danno
2013/04/02 21:08:47
Maybe I missed this, but where is the boilerplate
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
| |
9913 if (CanTransitionToMoreGeneralFastElementsKind(kind, packed)) { | |
danno
2013/04/02 21:08:47
Can you get rid of this? If you make a copy of the
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
| |
9914 AddInstruction(new(zone) HCheckMaps(boilerplate, map, zone)); | |
9915 } | |
9916 | |
9917 HValue* size_in_bytes = | |
9918 AddInstruction(new(zone) HConstant(size, Representation::Integer32())); | |
9919 HInstruction* object = | |
9920 AddInstruction(new(zone) HAllocate(context, | |
9921 size_in_bytes, | |
9922 HType::JSObject(), | |
9923 HAllocate::CAN_ALLOCATE_IN_NEW_SPACE)); | |
9924 int offset = 0; | |
9925 BuildEmitDeepCopy(boilerplate_object, object, boilerplate, &offset, mode, id); | |
9926 ASSERT_EQ(size, offset); | |
9927 return object; | |
9928 } | |
9929 | |
9930 | |
9931 void HOptimizedGraphBuilder::BuildEmitDeepCopy(Handle<JSObject> object, | |
9932 HInstruction* result, | |
9933 HInstruction* source, | |
danno
2013/04/02 21:08:47
I am not sure why you need to have both object and
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
| |
9934 int* offset, | |
9935 AllocationSiteMode mode, | |
9936 BailoutId id) { | |
9937 Zone* zone = this->zone(); | |
9938 Factory* factory = isolate()->factory(); | |
9939 | |
9940 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && | |
9941 object->map()->CanTrackAllocationSite(); | |
9942 | |
9943 // Only elements backing stores for non-COW arrays need to be copied. | |
9944 Handle<FixedArrayBase> elements(object->elements()); | |
9945 ElementsKind kind = object->map()->elements_kind(); | |
9946 bool has_elements = elements->length() > 0 && | |
9947 elements->map() != isolate()->heap()->fixed_cow_array_map(); | |
9948 | |
9949 // Increase the offset so that subsequent objects end up right after | |
9950 // this object and its backing store. | |
9951 int object_offset = *offset; | |
9952 int object_size = object->map()->instance_size(); | |
9953 int elements_size = has_elements ? elements->Size() : 0; | |
9954 int elements_offset = *offset + object_size; | |
9955 if (create_allocation_site_info) { | |
9956 elements_offset += AllocationSiteInfo::kSize; | |
9957 *offset += AllocationSiteInfo::kSize; | |
9958 } | |
9959 | |
9960 *offset += object_size + elements_size; | |
9961 | |
9962 // Copy object header. | |
9963 ASSERT(object->properties()->length() == 0); | |
9964 int inobject_properties = object->map()->inobject_properties(); | |
9965 int header_size = object_size - inobject_properties * kPointerSize; | |
9966 HValue* object_header = | |
9967 AddInstruction(new(zone) HInnerAllocatedObject(result, object_offset)); | |
9968 for (int i = 0; i < header_size; i += kPointerSize) { | |
danno
2013/04/02 21:08:47
Be careful here. Specifically, when you copy the o
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
| |
9969 HInstruction* header_value; | |
9970 if (has_elements && i == JSObject::kElementsOffset) { | |
9971 header_value = AddInstruction(new(zone) HInnerAllocatedObject( | |
9972 result, elements_offset)); | |
9973 | |
9974 } else { | |
9975 header_value = AddInstruction(new(zone) HLoadNamedField(source, true, i)); | |
danno
2013/04/02 21:08:47
Are you sure that it's OK not to deep copy the non
Hannes Payer (out of office)
2013/04/08 11:03:00
Now I am creating HConstants out of the boilerplat
| |
9976 } | |
9977 AddInstruction(new(zone) HStoreNamedField(object_header, | |
danno
2013/04/02 21:08:47
Have you considered loading the value you want to
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
| |
9978 factory->empty_string(), | |
9979 header_value, | |
9980 true, i)); | |
danno
2013/04/02 21:08:47
Needs to set the kChangesInobjectFields GVN flag
Hannes Payer (out of office)
2013/04/08 11:03:00
is done above.
| |
9981 AddSimulate(id); | |
9982 } | |
9983 | |
9984 // Copy in-object properties. | |
9985 HValue* object_properties = | |
9986 AddInstruction(new(zone) HInnerAllocatedObject(result, object_offset)); | |
9987 for (int i = 0; i < inobject_properties; i++) { | |
danno
2013/04/02 21:08:47
You need to be very careful here to honor the GVN
Hannes Payer (out of office)
2013/04/08 11:03:00
is taken care of by HStoreNamedField.
| |
9988 Handle<Object> value = Handle<Object>(object->InObjectPropertyAt(i), | |
9989 isolate()); | |
9990 if (value->IsJSObject()) { | |
9991 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | |
9992 HInstruction* value_instruction = | |
9993 AddInstruction(new(zone) HInnerAllocatedObject(result, *offset)); | |
9994 AddInstruction(new(zone) HStoreNamedField( | |
9995 object_properties, factory->empty_string(), value_instruction, true, | |
danno
2013/04/02 21:08:47
Instead of empty_string, perhaps we should add a "
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
| |
9996 object->GetInObjectPropertyOffset(i))); | |
9997 AddSimulate(id); | |
9998 source = AddInstruction(new(zone) HConstant( | |
danno
2013/04/02 21:08:47
name this something else, you mask the parameter c
Hannes Payer (out of office)
2013/04/08 11:03:00
removed
| |
9999 value, Representation::Tagged())); | |
10000 BuildEmitDeepCopy(value_object, result, source, offset, | |
10001 DONT_TRACK_ALLOCATION_SITE, id); | |
10002 } else { | |
10003 HInstruction* value_instruction = AddInstruction(new(zone) HConstant( | |
10004 value, Representation::Tagged())); | |
danno
2013/04/02 21:08:47
The value must be a smi, but without actually sett
Hannes Payer (out of office)
2013/04/08 11:03:00
This is determined by the HType and not by the Rep
| |
10005 AddInstruction(new(zone) HStoreNamedField( | |
10006 object_properties, factory->empty_string(), value_instruction, true, | |
10007 object->GetInObjectPropertyOffset(i))); | |
danno
2013/04/02 21:08:47
You need to be very careful here to honor the GVN
Hannes Payer (out of office)
2013/04/08 11:03:00
is done above.
| |
10008 AddSimulate(id); | |
10009 } | |
10010 } | |
10011 | |
10012 // Build Allocation Site Info if desired | |
10013 if (create_allocation_site_info) { | |
10014 HValue* alloc_site = | |
10015 AddInstruction(new(zone) HInnerAllocatedObject(result, JSArray::kSize)); | |
10016 Handle<Map> alloc_site_map(isolate()->heap()->allocation_site_info_map()); | |
10017 BuildStoreMap(alloc_site, alloc_site_map, id); | |
10018 int alloc_payload_offset = AllocationSiteInfo::kPayloadOffset; | |
10019 AddInstruction(new(zone) HStoreNamedField(alloc_site, | |
10020 factory->empty_string(), | |
danno
2013/04/02 21:08:47
create a "payload_string()"
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
| |
10021 source, | |
danno
2013/04/02 21:08:47
Can you really use the source for anything yet? It
Hannes Payer (out of office)
2013/04/08 11:03:00
I am using now the original_boilerplate.
| |
10022 true, alloc_payload_offset)); | |
10023 AddSimulate(id); | |
10024 } | |
10025 | |
10026 if (has_elements) { | |
10027 HValue* boilerplate_elements = | |
10028 AddInstruction(new(zone) HLoadElements(source, NULL)); | |
danno
2013/04/02 21:08:47
In this method have a mix here of loading from sou
Hannes Payer (out of office)
2013/04/08 11:03:00
I think it is the right thing to use HLoadElements
| |
10029 HValue* object_elements = | |
10030 AddInstruction(new(zone) HInnerAllocatedObject( | |
10031 result, elements_offset)); | |
10032 AddInstruction(new(zone) HStoreNamedField(object_elements, | |
danno
2013/04/02 21:08:47
Does this actually work? Why do you store boilerpl
Hannes Payer (out of office)
2013/04/08 11:03:00
Yes, this should be the same as what was done befo
| |
10033 factory->elements_field_string(), | |
10034 boilerplate_elements, | |
10035 true, JSObject::kElementsOffset)); | |
10036 AddSimulate(id); | |
10037 for (int i = 0; i < FixedArray::kHeaderSize; i += kPointerSize) { | |
danno
2013/04/02 21:08:47
Consider refactoring HGraphBuilder::BuildAllocateE
Hannes Payer (out of office)
2013/04/08 11:03:00
Done.
| |
10038 HInstruction* value_instruction = | |
10039 AddInstruction(new(zone) HLoadNamedField( | |
10040 boilerplate_elements, true, i)); | |
10041 AddInstruction(new(zone) HStoreNamedField(object_elements, | |
10042 factory->empty_string(), | |
10043 value_instruction, | |
10044 true, i)); | |
10045 AddSimulate(id); | |
10046 } | |
10047 | |
10048 // Copy elements backing store content. | |
10049 int elements_length = elements->length(); | |
danno
2013/04/02 21:08:47
I think you can use HGraphBuilder::BuildCopyElemen
Hannes Payer (out of office)
2013/04/08 11:03:00
I looked into it but the code below calls recursiv
| |
10050 if (elements->IsFixedDoubleArray()) { | |
10051 for (int i = 0; i < elements_length; i++) { | |
10052 HValue* key_constant = | |
10053 AddInstruction(new(zone) HConstant(i, Representation::Integer32())); | |
10054 HInstruction* value_instruction = | |
10055 AddInstruction(new(zone) HLoadKeyed( | |
10056 boilerplate_elements, key_constant, NULL, kind)); | |
10057 AddInstruction(new(zone) HStoreKeyed( | |
10058 object_elements, key_constant, value_instruction, kind)); | |
10059 AddSimulate(id); | |
10060 } | |
10061 } else if (elements->IsFixedArray()) { | |
10062 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | |
10063 for (int i = 0; i < elements_length; i++) { | |
10064 Handle<Object> value(fast_elements->get(i), isolate()); | |
10065 HValue* key_constant = | |
10066 AddInstruction(new(zone) HConstant(i, Representation::Integer32())); | |
10067 if (value->IsJSObject()) { | |
10068 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | |
10069 HInstruction* value_instruction = | |
10070 AddInstruction(new(zone) HInnerAllocatedObject(result, *offset)); | |
10071 AddInstruction(new(zone) HStoreKeyed( | |
10072 object_elements, key_constant, value_instruction, kind)); | |
10073 AddSimulate(id); | |
10074 source = AddInstruction(new(zone) HConstant( | |
10075 value_object, Representation::Tagged())); | |
10076 BuildEmitDeepCopy(value_object, result, source, offset, | |
10077 DONT_TRACK_ALLOCATION_SITE, id); | |
10078 } else { | |
10079 HInstruction* value_instruction = | |
10080 AddInstruction(new(zone) HLoadKeyed( | |
10081 boilerplate_elements, key_constant, NULL, kind)); | |
10082 AddInstruction(new(zone) HStoreKeyed( | |
10083 object_elements, key_constant, value_instruction, kind)); | |
10084 AddSimulate(id); | |
10085 } | |
10086 } | |
10087 } else { | |
10088 UNREACHABLE(); | |
10089 } | |
10090 } | |
10091 } | |
10092 | |
10093 | |
10094 | |
9900 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 10095 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
9901 ASSERT(!HasStackOverflow()); | 10096 ASSERT(!HasStackOverflow()); |
9902 ASSERT(current_block() != NULL); | 10097 ASSERT(current_block() != NULL); |
9903 ASSERT(current_block()->HasPredecessor()); | 10098 ASSERT(current_block()->HasPredecessor()); |
9904 HInstruction* instr = BuildThisFunction(); | 10099 HInstruction* instr = BuildThisFunction(); |
9905 return ast_context()->ReturnInstruction(instr, expr->id()); | 10100 return ast_context()->ReturnInstruction(instr, expr->id()); |
9906 } | 10101 } |
9907 | 10102 |
9908 | 10103 |
9909 void HOptimizedGraphBuilder::VisitDeclarations( | 10104 void HOptimizedGraphBuilder::VisitDeclarations( |
(...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11239 } | 11434 } |
11240 } | 11435 } |
11241 | 11436 |
11242 #ifdef DEBUG | 11437 #ifdef DEBUG |
11243 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11438 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
11244 if (allocator_ != NULL) allocator_->Verify(); | 11439 if (allocator_ != NULL) allocator_->Verify(); |
11245 #endif | 11440 #endif |
11246 } | 11441 } |
11247 | 11442 |
11248 } } // namespace v8::internal | 11443 } } // namespace v8::internal |
OLD | NEW |