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 ASSERT(map->has_fast_elements() || map->has_fast_double_elements()); |
3924 if (map->instance_type() == JS_ARRAY_TYPE) { | 3926 if (map->instance_type() == JS_ARRAY_TYPE) { |
3925 length = AddInstruction(new(zone()) HJSArrayLength(object)); | 3927 length = AddInstruction(new(zone()) HJSArrayLength(object)); |
3926 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3928 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3927 AddInstruction(elements); | 3929 AddInstruction(elements); |
3928 } else { | 3930 } else { |
3929 AddInstruction(elements); | 3931 AddInstruction(elements); |
3930 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 3932 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
3931 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3933 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3932 } | 3934 } |
| 3935 bool fast_double_elements = map->has_fast_double_elements(); |
3933 if (is_store) { | 3936 if (is_store) { |
3934 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); | 3937 if (fast_double_elements) { |
| 3938 return new(zone()) HStoreKeyedFastDoubleElement(elements, |
| 3939 checked_key, |
| 3940 val); |
| 3941 } else { |
| 3942 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); |
| 3943 } |
3935 } else { | 3944 } else { |
3936 return new(zone()) HLoadKeyedFastElement(elements, checked_key); | 3945 if (fast_double_elements) { |
| 3946 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); |
| 3947 } else { |
| 3948 return new(zone()) HLoadKeyedFastElement(elements, checked_key); |
| 3949 } |
3937 } | 3950 } |
3938 } | 3951 } |
3939 | 3952 |
3940 | 3953 |
3941 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, | 3954 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
3942 HValue* key, | 3955 HValue* key, |
3943 HValue* val, | 3956 HValue* val, |
3944 Expression* prop, | 3957 Expression* prop, |
3945 int ast_id, | 3958 int ast_id, |
3946 int position, | 3959 int position, |
(...skipping 12 matching lines...) Expand all Loading... |
3959 } | 3972 } |
3960 | 3973 |
3961 for (int i = 0; i < maps->length(); ++i) { | 3974 for (int i = 0; i < maps->length(); ++i) { |
3962 ASSERT(maps->at(i)->IsMap()); | 3975 ASSERT(maps->at(i)->IsMap()); |
3963 type_todo[maps->at(i)->elements_kind()] = true; | 3976 type_todo[maps->at(i)->elements_kind()] = true; |
3964 if (maps->at(i)->elements_kind() | 3977 if (maps->at(i)->elements_kind() |
3965 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { | 3978 >= JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { |
3966 todo_external_array = true; | 3979 todo_external_array = true; |
3967 } | 3980 } |
3968 } | 3981 } |
3969 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt. | |
3970 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false; | |
3971 | 3982 |
3972 HBasicBlock* join = graph()->CreateBasicBlock(); | 3983 HBasicBlock* join = graph()->CreateBasicBlock(); |
3973 | 3984 |
3974 HInstruction* elements_kind_instr = | 3985 HInstruction* elements_kind_instr = |
3975 AddInstruction(new(zone()) HElementsKind(object)); | 3986 AddInstruction(new(zone()) HElementsKind(object)); |
3976 HInstruction* elements = NULL; | 3987 HInstruction* elements = NULL; |
3977 HLoadExternalArrayPointer* external_elements = NULL; | 3988 HLoadExternalArrayPointer* external_elements = NULL; |
3978 HInstruction* checked_key = NULL; | 3989 HInstruction* checked_key = NULL; |
3979 | 3990 |
3980 // FAST_ELEMENTS is assumed to be the first case. | 3991 // FAST_ELEMENTS is assumed to be the first case. |
(...skipping 28 matching lines...) Expand all Loading... |
4009 HCompareConstantEqAndBranch* compare = | 4020 HCompareConstantEqAndBranch* compare = |
4010 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, | 4021 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, |
4011 elements_kind, | 4022 elements_kind, |
4012 Token::EQ_STRICT); | 4023 Token::EQ_STRICT); |
4013 compare->SetSuccessorAt(0, if_true); | 4024 compare->SetSuccessorAt(0, if_true); |
4014 compare->SetSuccessorAt(1, if_false); | 4025 compare->SetSuccessorAt(1, if_false); |
4015 current_block()->Finish(compare); | 4026 current_block()->Finish(compare); |
4016 | 4027 |
4017 set_current_block(if_true); | 4028 set_current_block(if_true); |
4018 HInstruction* access; | 4029 HInstruction* access; |
4019 if (elements_kind == JSObject::FAST_ELEMENTS) { | 4030 if (elements_kind == JSObject::FAST_ELEMENTS || |
| 4031 elements_kind == JSObject::FAST_DOUBLE_ELEMENTS) { |
4020 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 4032 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
4021 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 4033 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
4022 HHasInstanceTypeAndBranch* typecheck = | 4034 HHasInstanceTypeAndBranch* typecheck = |
4023 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 4035 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
4024 typecheck->SetSuccessorAt(0, if_jsarray); | 4036 typecheck->SetSuccessorAt(0, if_jsarray); |
4025 typecheck->SetSuccessorAt(1, if_fastobject); | 4037 typecheck->SetSuccessorAt(1, if_fastobject); |
4026 current_block()->Finish(typecheck); | 4038 current_block()->Finish(typecheck); |
4027 | 4039 |
4028 set_current_block(if_jsarray); | 4040 set_current_block(if_jsarray); |
4029 HInstruction* length = new(zone()) HJSArrayLength(object); | 4041 HInstruction* length = new(zone()) HJSArrayLength(object); |
4030 AddInstruction(length); | 4042 AddInstruction(length); |
4031 length->ClearFlag(HValue::kUseGVN); | 4043 length->ClearFlag(HValue::kUseGVN); |
4032 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4044 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4033 elements = AddInstruction(new(zone()) HLoadElements(object)); | 4045 elements = AddInstruction(new(zone()) HLoadElements(object)); |
4034 elements->ClearFlag(HValue::kUseGVN); | 4046 elements->ClearFlag(HValue::kUseGVN); |
| 4047 bool fast_double_elements = |
| 4048 elements_kind == JSObject::FAST_DOUBLE_ELEMENTS; |
4035 if (is_store) { | 4049 if (is_store) { |
4036 access = AddInstruction( | 4050 if (fast_double_elements) { |
4037 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4051 access = AddInstruction( |
| 4052 new(zone()) HStoreKeyedFastDoubleElement(elements, |
| 4053 checked_key, |
| 4054 val)); |
| 4055 } else { |
| 4056 access = AddInstruction( |
| 4057 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
| 4058 } |
4038 } else { | 4059 } else { |
4039 access = AddInstruction( | 4060 if (fast_double_elements) { |
4040 new(zone()) HLoadKeyedFastElement(elements, checked_key)); | 4061 access = AddInstruction( |
| 4062 new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key)); |
| 4063 } else { |
| 4064 access = AddInstruction( |
| 4065 new(zone()) HLoadKeyedFastElement(elements, checked_key)); |
| 4066 } |
4041 Push(access); | 4067 Push(access); |
4042 } | 4068 } |
4043 *has_side_effects |= access->HasSideEffects(); | 4069 *has_side_effects |= access->HasSideEffects(); |
4044 if (position != -1) { | 4070 if (position != -1) { |
4045 access->set_position(position); | 4071 access->set_position(position); |
4046 } | 4072 } |
4047 if_jsarray->Goto(join); | 4073 if_jsarray->Goto(join); |
4048 | 4074 |
4049 set_current_block(if_fastobject); | 4075 set_current_block(if_fastobject); |
4050 elements = AddInstruction(new(zone()) HLoadElements(object)); | 4076 elements = AddInstruction(new(zone()) HLoadElements(object)); |
4051 elements->ClearFlag(HValue::kUseGVN); | 4077 elements->ClearFlag(HValue::kUseGVN); |
4052 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 4078 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
4053 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4079 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4054 if (is_store) { | 4080 if (is_store) { |
4055 access = AddInstruction( | 4081 if (fast_double_elements) { |
4056 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4082 access = AddInstruction( |
| 4083 new(zone()) HStoreKeyedFastDoubleElement(elements, |
| 4084 checked_key, |
| 4085 val)); |
| 4086 } else { |
| 4087 access = AddInstruction( |
| 4088 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
| 4089 } |
4057 } else { | 4090 } else { |
4058 access = AddInstruction( | 4091 if (fast_double_elements) { |
4059 new(zone()) HLoadKeyedFastElement(elements, checked_key)); | 4092 access = AddInstruction( |
| 4093 new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key)); |
| 4094 } else { |
| 4095 access = AddInstruction( |
| 4096 new(zone()) HLoadKeyedFastElement(elements, checked_key)); |
| 4097 } |
4060 } | 4098 } |
4061 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { | 4099 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { |
4062 if (is_store) { | 4100 if (is_store) { |
4063 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); | 4101 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); |
4064 } else { | 4102 } else { |
4065 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); | 4103 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); |
4066 } | 4104 } |
4067 } else { // External array elements. | 4105 } else { // External array elements. |
4068 access = AddInstruction(BuildExternalArrayElementAccess( | 4106 access = AddInstruction(BuildExternalArrayElementAccess( |
4069 external_elements, checked_key, val, elements_kind, is_store)); | 4107 external_elements, checked_key, val, elements_kind, is_store)); |
(...skipping 2622 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6692 } | 6730 } |
6693 } | 6731 } |
6694 | 6732 |
6695 #ifdef DEBUG | 6733 #ifdef DEBUG |
6696 if (graph_ != NULL) graph_->Verify(); | 6734 if (graph_ != NULL) graph_->Verify(); |
6697 if (allocator_ != NULL) allocator_->Verify(); | 6735 if (allocator_ != NULL) allocator_->Verify(); |
6698 #endif | 6736 #endif |
6699 } | 6737 } |
6700 | 6738 |
6701 } } // namespace v8::internal | 6739 } } // namespace v8::internal |
OLD | NEW |