OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3894 } | 3894 } |
3895 | 3895 |
3896 | 3896 |
3897 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, | 3897 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, |
3898 HValue* key, | 3898 HValue* key, |
3899 HValue* val, | 3899 HValue* val, |
3900 Expression* expr, | 3900 Expression* expr, |
3901 bool is_store) { | 3901 bool is_store) { |
3902 ASSERT(expr->IsMonomorphic()); | 3902 ASSERT(expr->IsMonomorphic()); |
3903 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3903 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
3904 if (!map->has_fast_elements() && !map->has_external_array_elements()) { | 3904 if (!map->has_fast_elements() && |
| 3905 !map->has_fast_double_elements() && |
| 3906 !map->has_external_array_elements()) { |
3905 return is_store ? BuildStoreKeyedGeneric(object, key, val) | 3907 return is_store ? BuildStoreKeyedGeneric(object, key, val) |
3906 : BuildLoadKeyedGeneric(object, key); | 3908 : BuildLoadKeyedGeneric(object, key); |
3907 } | 3909 } |
3908 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3910 AddInstruction(new(zone()) HCheckNonSmi(object)); |
3909 AddInstruction(new(zone()) HCheckMap(object, map)); | 3911 AddInstruction(new(zone()) HCheckMap(object, map)); |
3910 HInstruction* elements = new(zone()) HLoadElements(object); | 3912 HInstruction* elements = new(zone()) HLoadElements(object); |
3911 HInstruction* length = NULL; | 3913 HInstruction* length = NULL; |
3912 HInstruction* checked_key = NULL; | 3914 HInstruction* checked_key = NULL; |
3913 if (map->has_external_array_elements()) { | 3915 if (map->has_external_array_elements()) { |
3914 AddInstruction(elements); | 3916 AddInstruction(elements); |
3915 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3917 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); |
3916 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3918 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3917 HLoadExternalArrayPointer* external_elements = | 3919 HLoadExternalArrayPointer* external_elements = |
3918 new(zone()) HLoadExternalArrayPointer(elements); | 3920 new(zone()) HLoadExternalArrayPointer(elements); |
3919 AddInstruction(external_elements); | 3921 AddInstruction(external_elements); |
3920 return BuildExternalArrayElementAccess(external_elements, checked_key, | 3922 return BuildExternalArrayElementAccess(external_elements, checked_key, |
3921 val, map->elements_kind(), is_store); | 3923 val, map->elements_kind(), is_store); |
3922 } | 3924 } |
3923 ASSERT(map->has_fast_elements()); | 3925 bool fast_double_elements = map->has_fast_double_elements(); |
| 3926 ASSERT(map->has_fast_elements() || fast_double_elements); |
3924 if (map->instance_type() == JS_ARRAY_TYPE) { | 3927 if (map->instance_type() == JS_ARRAY_TYPE) { |
3925 length = AddInstruction(new(zone()) HJSArrayLength(object)); | 3928 length = AddInstruction(new(zone()) HJSArrayLength(object)); |
3926 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3929 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3927 AddInstruction(elements); | 3930 AddInstruction(elements); |
3928 if (is_store) { | 3931 if (is_store && !fast_double_elements) { |
3929 AddInstruction(new(zone()) HCheckMap( | 3932 AddInstruction(new(zone()) HCheckMap( |
3930 elements, isolate()->factory()->fixed_array_map())); | 3933 elements, isolate()->factory()->fixed_array_map())); |
3931 } | 3934 } |
3932 } else { | 3935 } else { |
3933 AddInstruction(elements); | 3936 AddInstruction(elements); |
3934 if (is_store) { | 3937 if (is_store && !fast_double_elements) { |
3935 AddInstruction(new(zone()) HCheckMap( | 3938 AddInstruction(new(zone()) HCheckMap( |
3936 elements, isolate()->factory()->fixed_array_map())); | 3939 elements, isolate()->factory()->fixed_array_map())); |
3937 } | 3940 } |
3938 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 3941 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
3939 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3942 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3940 } | 3943 } |
3941 if (is_store) { | 3944 if (is_store) { |
3942 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); | 3945 if (fast_double_elements) { |
| 3946 return new(zone()) HStoreKeyedFastDoubleElement(elements, |
| 3947 checked_key, |
| 3948 val); |
| 3949 } else { |
| 3950 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); |
| 3951 } |
3943 } else { | 3952 } else { |
3944 return new(zone()) HLoadKeyedFastElement(elements, checked_key); | 3953 if (fast_double_elements) { |
| 3954 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); |
| 3955 } else { |
| 3956 return new(zone()) HLoadKeyedFastElement(elements, checked_key); |
| 3957 } |
3945 } | 3958 } |
3946 } | 3959 } |
3947 | 3960 |
3948 | 3961 |
3949 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, | 3962 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
3950 HValue* key, | 3963 HValue* key, |
3951 HValue* val, | 3964 HValue* val, |
3952 Expression* prop, | 3965 Expression* prop, |
3953 int ast_id, | 3966 int ast_id, |
3954 int position, | 3967 int position, |
(...skipping 12 matching lines...) Expand all Loading... |
3967 } | 3980 } |
3968 | 3981 |
3969 for (int i = 0; i < maps->length(); ++i) { | 3982 for (int i = 0; i < maps->length(); ++i) { |
3970 ASSERT(maps->at(i)->IsMap()); | 3983 ASSERT(maps->at(i)->IsMap()); |
3971 type_todo[maps->at(i)->elements_kind()] = true; | 3984 type_todo[maps->at(i)->elements_kind()] = true; |
3972 if (maps->at(i)->elements_kind() | 3985 if (maps->at(i)->elements_kind() |
3973 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { | 3986 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { |
3974 todo_external_array = true; | 3987 todo_external_array = true; |
3975 } | 3988 } |
3976 } | 3989 } |
3977 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt. | |
3978 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false; | |
3979 | 3990 |
3980 HBasicBlock* join = graph()->CreateBasicBlock(); | 3991 HBasicBlock* join = graph()->CreateBasicBlock(); |
3981 | 3992 |
3982 HInstruction* elements_kind_instr = | 3993 HInstruction* elements_kind_instr = |
3983 AddInstruction(new(zone()) HElementsKind(object)); | 3994 AddInstruction(new(zone()) HElementsKind(object)); |
3984 HInstruction* elements = NULL; | 3995 HInstruction* elements = NULL; |
3985 HLoadExternalArrayPointer* external_elements = NULL; | 3996 HLoadExternalArrayPointer* external_elements = NULL; |
3986 HInstruction* checked_key = NULL; | 3997 HInstruction* checked_key = NULL; |
3987 | 3998 |
3988 // FAST_ELEMENTS is assumed to be the first case. | 3999 // FAST_ELEMENTS is assumed to be the first case. |
(...skipping 28 matching lines...) Expand all Loading... |
4017 HCompareConstantEqAndBranch* compare = | 4028 HCompareConstantEqAndBranch* compare = |
4018 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, | 4029 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, |
4019 elements_kind, | 4030 elements_kind, |
4020 Token::EQ_STRICT); | 4031 Token::EQ_STRICT); |
4021 compare->SetSuccessorAt(0, if_true); | 4032 compare->SetSuccessorAt(0, if_true); |
4022 compare->SetSuccessorAt(1, if_false); | 4033 compare->SetSuccessorAt(1, if_false); |
4023 current_block()->Finish(compare); | 4034 current_block()->Finish(compare); |
4024 | 4035 |
4025 set_current_block(if_true); | 4036 set_current_block(if_true); |
4026 HInstruction* access; | 4037 HInstruction* access; |
4027 if (elements_kind == JSObject::FAST_ELEMENTS) { | 4038 if (elements_kind == JSObject::FAST_ELEMENTS || |
| 4039 elements_kind == JSObject::FAST_DOUBLE_ELEMENTS) { |
4028 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 4040 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
4029 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 4041 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
4030 HHasInstanceTypeAndBranch* typecheck = | 4042 HHasInstanceTypeAndBranch* typecheck = |
4031 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 4043 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
4032 typecheck->SetSuccessorAt(0, if_jsarray); | 4044 typecheck->SetSuccessorAt(0, if_jsarray); |
4033 typecheck->SetSuccessorAt(1, if_fastobject); | 4045 typecheck->SetSuccessorAt(1, if_fastobject); |
4034 current_block()->Finish(typecheck); | 4046 current_block()->Finish(typecheck); |
4035 | 4047 |
4036 set_current_block(if_jsarray); | 4048 set_current_block(if_jsarray); |
4037 HInstruction* length = new(zone()) HJSArrayLength(object); | 4049 HInstruction* length = new(zone()) HJSArrayLength(object); |
4038 AddInstruction(length); | 4050 AddInstruction(length); |
4039 length->ClearFlag(HValue::kUseGVN); | 4051 length->ClearFlag(HValue::kUseGVN); |
4040 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4052 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4041 elements = AddInstruction(new(zone()) HLoadElements(object)); | 4053 elements = AddInstruction(new(zone()) HLoadElements(object)); |
4042 elements->ClearFlag(HValue::kUseGVN); | 4054 elements->ClearFlag(HValue::kUseGVN); |
| 4055 bool fast_double_elements = |
| 4056 elements_kind == JSObject::FAST_DOUBLE_ELEMENTS; |
4043 if (is_store) { | 4057 if (is_store) { |
4044 AddInstruction(new(zone()) HCheckMap( | 4058 if (fast_double_elements) { |
4045 elements, isolate()->factory()->fixed_array_map())); | 4059 access = AddInstruction( |
4046 access = AddInstruction( | 4060 new(zone()) HStoreKeyedFastDoubleElement(elements, |
4047 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4061 checked_key, |
| 4062 val)); |
| 4063 } else { |
| 4064 AddInstruction(new(zone()) HCheckMap( |
| 4065 elements, isolate()->factory()->fixed_array_map())); |
| 4066 access = AddInstruction( |
| 4067 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
| 4068 } |
4048 } else { | 4069 } else { |
4049 access = AddInstruction( | 4070 if (fast_double_elements) { |
4050 new(zone()) HLoadKeyedFastElement(elements, checked_key)); | 4071 access = AddInstruction( |
| 4072 new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key)); |
| 4073 } else { |
| 4074 access = AddInstruction( |
| 4075 new(zone()) HLoadKeyedFastElement(elements, checked_key)); |
| 4076 } |
4051 Push(access); | 4077 Push(access); |
4052 } | 4078 } |
4053 *has_side_effects |= access->HasSideEffects(); | 4079 *has_side_effects |= access->HasSideEffects(); |
4054 if (position != -1) { | 4080 if (position != -1) { |
4055 access->set_position(position); | 4081 access->set_position(position); |
4056 } | 4082 } |
4057 if_jsarray->Goto(join); | 4083 if_jsarray->Goto(join); |
4058 | 4084 |
4059 set_current_block(if_fastobject); | 4085 set_current_block(if_fastobject); |
4060 elements = AddInstruction(new(zone()) HLoadElements(object)); | 4086 elements = AddInstruction(new(zone()) HLoadElements(object)); |
4061 elements->ClearFlag(HValue::kUseGVN); | 4087 elements->ClearFlag(HValue::kUseGVN); |
4062 if (is_store) { | 4088 if (is_store && !fast_double_elements) { |
4063 AddInstruction(new(zone()) HCheckMap( | 4089 AddInstruction(new(zone()) HCheckMap( |
4064 elements, isolate()->factory()->fixed_array_map())); | 4090 elements, isolate()->factory()->fixed_array_map())); |
4065 } | 4091 } |
4066 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 4092 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
4067 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4093 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4068 if (is_store) { | 4094 if (is_store) { |
4069 access = AddInstruction( | 4095 if (fast_double_elements) { |
4070 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4096 access = AddInstruction( |
| 4097 new(zone()) HStoreKeyedFastDoubleElement(elements, |
| 4098 checked_key, |
| 4099 val)); |
| 4100 } else { |
| 4101 access = AddInstruction( |
| 4102 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
| 4103 } |
4071 } else { | 4104 } else { |
4072 access = AddInstruction( | 4105 if (fast_double_elements) { |
4073 new(zone()) HLoadKeyedFastElement(elements, checked_key)); | 4106 access = AddInstruction( |
| 4107 new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key)); |
| 4108 } else { |
| 4109 access = AddInstruction( |
| 4110 new(zone()) HLoadKeyedFastElement(elements, checked_key)); |
| 4111 } |
4074 } | 4112 } |
4075 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { | 4113 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { |
4076 if (is_store) { | 4114 if (is_store) { |
4077 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 4115 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
4078 } else { | 4116 } else { |
4079 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 4117 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
4080 } | 4118 } |
4081 } else { // External array elements. | 4119 } else { // External array elements. |
4082 access = AddInstruction(BuildExternalArrayElementAccess( | 4120 access = AddInstruction(BuildExternalArrayElementAccess( |
4083 external_elements, checked_key, val, elements_kind, is_store)); | 4121 external_elements, checked_key, val, elements_kind, is_store)); |
(...skipping 2622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6706 } | 6744 } |
6707 } | 6745 } |
6708 | 6746 |
6709 #ifdef DEBUG | 6747 #ifdef DEBUG |
6710 if (graph_ != NULL) graph_->Verify(); | 6748 if (graph_ != NULL) graph_->Verify(); |
6711 if (allocator_ != NULL) allocator_->Verify(); | 6749 if (allocator_ != NULL) allocator_->Verify(); |
6712 #endif | 6750 #endif |
6713 } | 6751 } |
6714 | 6752 |
6715 } } // namespace v8::internal | 6753 } } // namespace v8::internal |
OLD | NEW |