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 1568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1579 | 1579 |
1580 HValue* element = | 1580 HValue* element = |
1581 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, | 1581 AddInstruction(new(zone()) HLoadKeyed(from_elements, key, NULL, |
1582 from_elements_kind, | 1582 from_elements_kind, |
1583 ALLOW_RETURN_HOLE)); | 1583 ALLOW_RETURN_HOLE)); |
1584 | 1584 |
1585 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) | 1585 ElementsKind holey_kind = IsFastSmiElementsKind(to_elements_kind) |
1586 ? FAST_HOLEY_ELEMENTS : to_elements_kind; | 1586 ? FAST_HOLEY_ELEMENTS : to_elements_kind; |
1587 HInstruction* holey_store = AddInstruction( | 1587 HInstruction* holey_store = AddInstruction( |
1588 new(zone()) HStoreKeyed(to_elements, key, element, holey_kind)); | 1588 new(zone()) HStoreKeyed(to_elements, key, element, holey_kind)); |
1589 holey_store->ClearFlag(HValue::kDeoptimizeOnUndefined); | 1589 // Allow NaN hole values to converted to their tagged counterparts. |
| 1590 if (IsFastHoleyElementsKind(to_elements_kind)) { |
| 1591 holey_store->SetFlag(HValue::kAllowUndefinedAsNaN); |
| 1592 } |
1590 | 1593 |
1591 builder.EndBody(); | 1594 builder.EndBody(); |
1592 | 1595 |
1593 if (!pre_fill_with_holes && length != capacity) { | 1596 if (!pre_fill_with_holes && length != capacity) { |
1594 // Fill unused capacity with the hole. | 1597 // Fill unused capacity with the hole. |
1595 BuildFillElementsWithHole(context, to_elements, to_elements_kind, | 1598 BuildFillElementsWithHole(context, to_elements, to_elements_kind, |
1596 key, capacity); | 1599 key, capacity); |
1597 } | 1600 } |
1598 } | 1601 } |
1599 | 1602 |
(...skipping 1493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3093 next = use_value->block()->predecessors()->at(use_index)->end(); | 3096 next = use_value->block()->predecessors()->at(use_index)->end(); |
3094 } else { | 3097 } else { |
3095 next = HInstruction::cast(use_value); | 3098 next = HInstruction::cast(use_value); |
3096 } | 3099 } |
3097 // For constants we try to make the representation change at compile | 3100 // For constants we try to make the representation change at compile |
3098 // time. When a representation change is not possible without loss of | 3101 // time. When a representation change is not possible without loss of |
3099 // information we treat constants like normal instructions and insert the | 3102 // information we treat constants like normal instructions and insert the |
3100 // change instructions for them. | 3103 // change instructions for them. |
3101 HInstruction* new_value = NULL; | 3104 HInstruction* new_value = NULL; |
3102 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); | 3105 bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); |
3103 bool deoptimize_on_undefined = | 3106 bool allow_undefined_as_nan = |
3104 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined); | 3107 use_value->CheckFlag(HValue::kAllowUndefinedAsNaN); |
3105 if (value->IsConstant()) { | 3108 if (value->IsConstant()) { |
3106 HConstant* constant = HConstant::cast(value); | 3109 HConstant* constant = HConstant::cast(value); |
3107 // Try to create a new copy of the constant with the new representation. | 3110 // Try to create a new copy of the constant with the new representation. |
3108 new_value = (is_truncating && to.IsInteger32()) | 3111 new_value = (is_truncating && to.IsInteger32()) |
3109 ? constant->CopyToTruncatedInt32(zone()) | 3112 ? constant->CopyToTruncatedInt32(zone()) |
3110 : constant->CopyToRepresentation(to, zone()); | 3113 : constant->CopyToRepresentation(to, zone()); |
3111 } | 3114 } |
3112 | 3115 |
3113 if (new_value == NULL) { | 3116 if (new_value == NULL) { |
3114 new_value = new(zone()) HChange(value, to, | 3117 new_value = new(zone()) HChange(value, to, |
3115 is_truncating, deoptimize_on_undefined); | 3118 is_truncating, allow_undefined_as_nan); |
3116 } | 3119 } |
3117 | 3120 |
3118 new_value->InsertBefore(next); | 3121 new_value->InsertBefore(next); |
3119 use_value->SetOperandAt(use_index, new_value); | 3122 use_value->SetOperandAt(use_index, new_value); |
3120 } | 3123 } |
3121 | 3124 |
3122 | 3125 |
3123 void HGraph::InsertRepresentationChangesForValue(HValue* value) { | 3126 void HGraph::InsertRepresentationChangesForValue(HValue* value) { |
3124 Representation r = value->representation(); | 3127 Representation r = value->representation(); |
3125 if (r.IsNone()) return; | 3128 if (r.IsNone()) return; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3212 while (current != NULL) { | 3215 while (current != NULL) { |
3213 HInstruction* next = current->next(); | 3216 HInstruction* next = current->next(); |
3214 InsertRepresentationChangesForValue(current); | 3217 InsertRepresentationChangesForValue(current); |
3215 current = next; | 3218 current = next; |
3216 } | 3219 } |
3217 } | 3220 } |
3218 } | 3221 } |
3219 | 3222 |
3220 | 3223 |
3221 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { | 3224 void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { |
3222 if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return; | 3225 if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return; |
3223 phi->SetFlag(HValue::kDeoptimizeOnUndefined); | 3226 phi->ClearFlag(HValue::kAllowUndefinedAsNaN); |
3224 for (int i = 0; i < phi->OperandCount(); ++i) { | 3227 for (int i = 0; i < phi->OperandCount(); ++i) { |
3225 HValue* input = phi->OperandAt(i); | 3228 HValue* input = phi->OperandAt(i); |
3226 if (input->IsPhi()) { | 3229 if (input->IsPhi()) { |
3227 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); | 3230 RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); |
3228 } | 3231 } |
3229 } | 3232 } |
3230 } | 3233 } |
3231 | 3234 |
3232 | 3235 |
3233 void HGraph::MarkDeoptimizeOnUndefined() { | 3236 void HGraph::MarkDeoptimizeOnUndefined() { |
3234 HPhase phase("H_MarkDeoptimizeOnUndefined", this); | 3237 HPhase phase("H_MarkDeoptimizeOnUndefined", this); |
3235 // Compute DeoptimizeOnUndefined flag for phis. | 3238 // Compute DeoptimizeOnUndefined flag for phis. |
3236 // Any phi that can reach a use with DeoptimizeOnUndefined set must | 3239 // Any phi that can reach a use with DeoptimizeOnUndefined set must |
3237 // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with | 3240 // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with |
3238 // double input representation, has this flag set. | 3241 // double input representation, has this flag set. |
3239 // The flag is used by HChange tagged->double, which must deoptimize | 3242 // The flag is used by HChange tagged->double, which must deoptimize |
3240 // if one of its uses has this flag set. | 3243 // if one of its uses has this flag set. |
3241 for (int i = 0; i < phi_list()->length(); i++) { | 3244 for (int i = 0; i < phi_list()->length(); i++) { |
3242 HPhi* phi = phi_list()->at(i); | 3245 HPhi* phi = phi_list()->at(i); |
3243 if (phi->representation().IsDouble()) { | 3246 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
3244 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { | 3247 HValue* use_value = it.value(); |
3245 int use_index = it.index(); | 3248 if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) { |
3246 HValue* use_value = it.value(); | 3249 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); |
3247 Representation req = use_value->RequiredInputRepresentation(use_index); | 3250 break; |
3248 if (!req.IsDouble() || | |
3249 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined)) { | |
3250 RecursivelyMarkPhiDeoptimizeOnUndefined(phi); | |
3251 break; | |
3252 } | |
3253 } | 3251 } |
3254 } | 3252 } |
3255 } | 3253 } |
3256 } | 3254 } |
3257 | 3255 |
3258 | 3256 |
3259 // Discover instructions that can be marked with kUint32 flag allowing | 3257 // Discover instructions that can be marked with kUint32 flag allowing |
3260 // them to produce full range uint32 values. | 3258 // them to produce full range uint32 values. |
3261 class Uint32Analysis BASE_EMBEDDED { | 3259 class Uint32Analysis BASE_EMBEDDED { |
3262 public: | 3260 public: |
(...skipping 6839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10102 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( | 10100 HInstruction* boilerplate_elements = AddInstruction(new(zone) HConstant( |
10103 elements, Representation::Tagged())); | 10101 elements, Representation::Tagged())); |
10104 int elements_length = elements->length(); | 10102 int elements_length = elements->length(); |
10105 for (int i = 0; i < elements_length; i++) { | 10103 for (int i = 0; i < elements_length; i++) { |
10106 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); | 10104 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); |
10107 HInstruction* value_instruction = | 10105 HInstruction* value_instruction = |
10108 AddInstruction(new(zone) HLoadKeyed( | 10106 AddInstruction(new(zone) HLoadKeyed( |
10109 boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE)); | 10107 boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE)); |
10110 HInstruction* store = AddInstruction(new(zone) HStoreKeyed( | 10108 HInstruction* store = AddInstruction(new(zone) HStoreKeyed( |
10111 object_elements, key_constant, value_instruction, kind)); | 10109 object_elements, key_constant, value_instruction, kind)); |
10112 store->ClearFlag(HValue::kDeoptimizeOnUndefined); | 10110 store->SetFlag(HValue::kAllowUndefinedAsNaN); |
10113 } | 10111 } |
10114 } | 10112 } |
10115 | 10113 |
10116 | 10114 |
10117 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 10115 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
10118 Handle<FixedArrayBase> elements, | 10116 Handle<FixedArrayBase> elements, |
10119 Handle<FixedArrayBase> original_elements, | 10117 Handle<FixedArrayBase> original_elements, |
10120 ElementsKind kind, | 10118 ElementsKind kind, |
10121 HValue* object_elements, | 10119 HValue* object_elements, |
10122 HInstruction* target, | 10120 HInstruction* target, |
(...skipping 1375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11498 } | 11496 } |
11499 } | 11497 } |
11500 | 11498 |
11501 #ifdef DEBUG | 11499 #ifdef DEBUG |
11502 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11500 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
11503 if (allocator_ != NULL) allocator_->Verify(); | 11501 if (allocator_ != NULL) allocator_->Verify(); |
11504 #endif | 11502 #endif |
11505 } | 11503 } |
11506 | 11504 |
11507 } } // namespace v8::internal | 11505 } } // namespace v8::internal |
OLD | NEW |