| 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 3256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3267 // If the subexpression is a literal or a simple materialized literal it | 3267 // If the subexpression is a literal or a simple materialized literal it |
| 3268 // is already set in the cloned array. | 3268 // is already set in the cloned array. |
| 3269 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 3269 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 3270 | 3270 |
| 3271 CHECK_ALIVE(VisitForValue(subexpr)); | 3271 CHECK_ALIVE(VisitForValue(subexpr)); |
| 3272 HValue* value = Pop(); | 3272 HValue* value = Pop(); |
| 3273 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); | 3273 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); |
| 3274 | 3274 |
| 3275 // Load the elements array before the first store. | 3275 // Load the elements array before the first store. |
| 3276 if (elements == NULL) { | 3276 if (elements == NULL) { |
| 3277 elements = new(zone()) HLoadElements(literal); | 3277 elements = new(zone()) HLoadElements(literal); |
| 3278 AddInstruction(elements); | 3278 AddInstruction(elements); |
| 3279 } | 3279 } |
| 3280 | 3280 |
| 3281 HValue* key = AddInstruction( | 3281 HValue* key = AddInstruction( |
| 3282 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), | 3282 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), |
| 3283 Representation::Integer32())); | 3283 Representation::Integer32())); |
| 3284 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); | 3284 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); |
| 3285 AddSimulate(expr->GetIdForElement(i)); | 3285 AddSimulate(expr->GetIdForElement(i)); |
| 3286 } | 3286 } |
| 3287 return ast_context()->ReturnValue(Pop()); | 3287 return ast_context()->ReturnValue(Pop()); |
| 3288 } | 3288 } |
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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() && !map->has_external_array_elements()) { |
| 3905 return is_store ? BuildStoreKeyedGeneric(object, key, val) | 3905 return is_store ? BuildStoreKeyedGeneric(object, key, val) |
| 3906 : BuildLoadKeyedGeneric(object, key); | 3906 : BuildLoadKeyedGeneric(object, key); |
| 3907 } | 3907 } |
| 3908 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3908 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3909 AddInstruction(new(zone()) HCheckMap(object, map)); | 3909 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3910 HInstruction* elements = new(zone()) HLoadElements(object); | 3910 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
| 3911 if (is_store) { |
| 3912 AddInstruction(new(zone()) HCheckMap( |
| 3913 elements, isolate()->factory()->fixed_array_map())); |
| 3914 } |
| 3911 HInstruction* length = NULL; | 3915 HInstruction* length = NULL; |
| 3912 HInstruction* checked_key = NULL; | 3916 HInstruction* checked_key = NULL; |
| 3913 if (map->has_external_array_elements()) { | 3917 if (map->has_external_array_elements()) { |
| 3914 AddInstruction(elements); | |
| 3915 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3918 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); |
| 3916 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3919 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3917 HLoadExternalArrayPointer* external_elements = | 3920 HLoadExternalArrayPointer* external_elements = |
| 3918 new(zone()) HLoadExternalArrayPointer(elements); | 3921 new(zone()) HLoadExternalArrayPointer(elements); |
| 3919 AddInstruction(external_elements); | 3922 AddInstruction(external_elements); |
| 3920 return BuildExternalArrayElementAccess(external_elements, checked_key, | 3923 return BuildExternalArrayElementAccess(external_elements, checked_key, |
| 3921 val, map->elements_kind(), is_store); | 3924 val, map->elements_kind(), is_store); |
| 3922 } | 3925 } |
| 3923 ASSERT(map->has_fast_elements()); | 3926 ASSERT(map->has_fast_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, mapcheck)); |
| 3926 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | |
| 3927 AddInstruction(elements); | |
| 3928 if (is_store) { | |
| 3929 AddInstruction(new(zone()) HCheckMap( | |
| 3930 elements, isolate()->factory()->fixed_array_map())); | |
| 3931 } | |
| 3932 } else { | 3929 } else { |
| 3933 AddInstruction(elements); | |
| 3934 if (is_store) { | |
| 3935 AddInstruction(new(zone()) HCheckMap( | |
| 3936 elements, isolate()->factory()->fixed_array_map())); | |
| 3937 } | |
| 3938 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 3930 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
| 3939 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | |
| 3940 } | 3931 } |
| 3932 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3941 if (is_store) { | 3933 if (is_store) { |
| 3942 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); | 3934 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); |
| 3943 } else { | 3935 } else { |
| 3944 return new(zone()) HLoadKeyedFastElement(elements, checked_key); | 3936 return new(zone()) HLoadKeyedFastElement(elements, checked_key); |
| 3945 } | 3937 } |
| 3946 } | 3938 } |
| 3947 | 3939 |
| 3948 | 3940 |
| 3949 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, | 3941 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, |
| 3950 HValue* key, | 3942 HValue* key, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3974 todo_external_array = true; | 3966 todo_external_array = true; |
| 3975 } | 3967 } |
| 3976 } | 3968 } |
| 3977 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt. | 3969 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt. |
| 3978 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false; | 3970 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false; |
| 3979 | 3971 |
| 3980 HBasicBlock* join = graph()->CreateBasicBlock(); | 3972 HBasicBlock* join = graph()->CreateBasicBlock(); |
| 3981 | 3973 |
| 3982 HInstruction* elements_kind_instr = | 3974 HInstruction* elements_kind_instr = |
| 3983 AddInstruction(new(zone()) HElementsKind(object)); | 3975 AddInstruction(new(zone()) HElementsKind(object)); |
| 3984 HInstruction* elements = NULL; | 3976 HCompareConstantEqAndBranch* elements_kind_branch = NULL; |
| 3977 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
| 3985 HLoadExternalArrayPointer* external_elements = NULL; | 3978 HLoadExternalArrayPointer* external_elements = NULL; |
| 3986 HInstruction* checked_key = NULL; | 3979 HInstruction* checked_key = NULL; |
| 3987 | 3980 |
| 3988 // FAST_ELEMENTS is assumed to be the first case. | 3981 // FAST_ELEMENTS is assumed to be the first case. |
| 3989 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0); | 3982 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0); |
| 3990 | 3983 |
| 3991 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; | 3984 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; |
| 3992 elements_kind <= JSObject::LAST_ELEMENTS_KIND; | 3985 elements_kind <= JSObject::LAST_ELEMENTS_KIND; |
| 3993 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { | 3986 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { |
| 3994 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we | 3987 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we |
| 3995 // need to add some code that's executed for all external array cases. | 3988 // need to add some code that's executed for all external array cases. |
| 3996 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 3989 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
| 3997 JSObject::LAST_ELEMENTS_KIND); | 3990 JSObject::LAST_ELEMENTS_KIND); |
| 3998 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 3991 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
| 3999 && todo_external_array) { | 3992 && todo_external_array) { |
| 4000 elements = AddInstruction(new(zone()) HLoadElements(object)); | |
| 4001 // We need to forcibly prevent some ElementsKind-dependent instructions | |
| 4002 // from being hoisted out of any loops they might occur in, because | |
| 4003 // the current loop-invariant-code-motion algorithm isn't clever enough | |
| 4004 // to deal with them properly. | |
| 4005 // There's some performance to be gained by developing a smarter | |
| 4006 // solution for this. | |
| 4007 elements->ClearFlag(HValue::kUseGVN); | |
| 4008 HInstruction* length = | 3993 HInstruction* length = |
| 4009 AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3994 AddInstruction(new(zone()) HExternalArrayLength(elements)); |
| 4010 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3995 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 4011 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 3996 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
| 4012 AddInstruction(external_elements); | 3997 AddInstruction(external_elements); |
| 4013 } | 3998 } |
| 4014 if (type_todo[elements_kind]) { | 3999 if (type_todo[elements_kind]) { |
| 4015 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 4000 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 4016 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4001 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 4017 HCompareConstantEqAndBranch* compare = | 4002 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( |
| 4018 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, | 4003 elements_kind_instr, elements_kind, Token::EQ_STRICT); |
| 4019 elements_kind, | 4004 elements_kind_branch->SetSuccessorAt(0, if_true); |
| 4020 Token::EQ_STRICT); | 4005 elements_kind_branch->SetSuccessorAt(1, if_false); |
| 4021 compare->SetSuccessorAt(0, if_true); | 4006 current_block()->Finish(elements_kind_branch); |
| 4022 compare->SetSuccessorAt(1, if_false); | |
| 4023 current_block()->Finish(compare); | |
| 4024 | 4007 |
| 4025 set_current_block(if_true); | 4008 set_current_block(if_true); |
| 4026 HInstruction* access; | 4009 HInstruction* access; |
| 4027 if (elements_kind == JSObject::FAST_ELEMENTS) { | 4010 if (elements_kind == JSObject::FAST_ELEMENTS) { |
| 4011 if (is_store) { |
| 4012 AddInstruction(new(zone()) HCheckMap( |
| 4013 elements, isolate()->factory()->fixed_array_map())); |
| 4014 } |
| 4028 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 4015 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
| 4029 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 4016 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
| 4030 HHasInstanceTypeAndBranch* typecheck = | 4017 HHasInstanceTypeAndBranch* typecheck = |
| 4031 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 4018 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
| 4032 typecheck->SetSuccessorAt(0, if_jsarray); | 4019 typecheck->SetSuccessorAt(0, if_jsarray); |
| 4033 typecheck->SetSuccessorAt(1, if_fastobject); | 4020 typecheck->SetSuccessorAt(1, if_fastobject); |
| 4034 current_block()->Finish(typecheck); | 4021 current_block()->Finish(typecheck); |
| 4035 | 4022 |
| 4036 set_current_block(if_jsarray); | 4023 set_current_block(if_jsarray); |
| 4037 HInstruction* length = new(zone()) HJSArrayLength(object); | 4024 HInstruction* length = new(zone()) HJSArrayLength(object, typecheck); |
| 4038 AddInstruction(length); | 4025 AddInstruction(length); |
| 4039 length->ClearFlag(HValue::kUseGVN); | |
| 4040 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4026 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 4041 elements = AddInstruction(new(zone()) HLoadElements(object)); | |
| 4042 elements->ClearFlag(HValue::kUseGVN); | |
| 4043 if (is_store) { | 4027 if (is_store) { |
| 4044 AddInstruction(new(zone()) HCheckMap( | |
| 4045 elements, isolate()->factory()->fixed_array_map())); | |
| 4046 access = AddInstruction( | 4028 access = AddInstruction( |
| 4047 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4029 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
| 4048 } else { | 4030 } else { |
| 4049 access = AddInstruction( | 4031 access = AddInstruction( |
| 4050 new(zone()) HLoadKeyedFastElement(elements, checked_key)); | 4032 new(zone()) HLoadKeyedFastElement(elements, checked_key)); |
| 4051 Push(access); | 4033 Push(access); |
| 4052 } | 4034 } |
| 4053 *has_side_effects |= access->HasSideEffects(); | 4035 *has_side_effects |= access->HasSideEffects(); |
| 4054 if (position != -1) { | 4036 if (position != -1) { |
| 4055 access->set_position(position); | 4037 access->set_position(position); |
| 4056 } | 4038 } |
| 4057 if_jsarray->Goto(join); | 4039 if_jsarray->Goto(join); |
| 4058 | 4040 |
| 4059 set_current_block(if_fastobject); | 4041 set_current_block(if_fastobject); |
| 4060 elements = AddInstruction(new(zone()) HLoadElements(object)); | |
| 4061 elements->ClearFlag(HValue::kUseGVN); | |
| 4062 if (is_store) { | |
| 4063 AddInstruction(new(zone()) HCheckMap( | |
| 4064 elements, isolate()->factory()->fixed_array_map())); | |
| 4065 } | |
| 4066 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 4042 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
| 4067 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4043 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 4068 if (is_store) { | 4044 if (is_store) { |
| 4069 access = AddInstruction( | 4045 access = AddInstruction( |
| 4070 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4046 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
| 4071 } else { | 4047 } else { |
| 4072 access = AddInstruction( | 4048 access = AddInstruction( |
| 4073 new(zone()) HLoadKeyedFastElement(elements, checked_key)); | 4049 new(zone()) HLoadKeyedFastElement(elements, checked_key)); |
| 4074 } | 4050 } |
| 4075 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { | 4051 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4188 expr->RecordTypeFeedback(oracle()); | 4164 expr->RecordTypeFeedback(oracle()); |
| 4189 | 4165 |
| 4190 if (TryArgumentsAccess(expr)) return; | 4166 if (TryArgumentsAccess(expr)) return; |
| 4191 | 4167 |
| 4192 CHECK_ALIVE(VisitForValue(expr->obj())); | 4168 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 4193 | 4169 |
| 4194 HInstruction* instr = NULL; | 4170 HInstruction* instr = NULL; |
| 4195 if (expr->IsArrayLength()) { | 4171 if (expr->IsArrayLength()) { |
| 4196 HValue* array = Pop(); | 4172 HValue* array = Pop(); |
| 4197 AddInstruction(new(zone()) HCheckNonSmi(array)); | 4173 AddInstruction(new(zone()) HCheckNonSmi(array)); |
| 4198 AddInstruction(HCheckInstanceType::NewIsJSArray(array)); | 4174 HInstruction* mapcheck = |
| 4199 instr = new(zone()) HJSArrayLength(array); | 4175 AddInstruction(HCheckInstanceType::NewIsJSArray(array)); |
| 4176 instr = new(zone()) HJSArrayLength(array, mapcheck); |
| 4200 | 4177 |
| 4201 } else if (expr->IsStringLength()) { | 4178 } else if (expr->IsStringLength()) { |
| 4202 HValue* string = Pop(); | 4179 HValue* string = Pop(); |
| 4203 AddInstruction(new(zone()) HCheckNonSmi(string)); | 4180 AddInstruction(new(zone()) HCheckNonSmi(string)); |
| 4204 AddInstruction(HCheckInstanceType::NewIsString(string)); | 4181 AddInstruction(HCheckInstanceType::NewIsString(string)); |
| 4205 instr = new(zone()) HStringLength(string); | 4182 instr = new(zone()) HStringLength(string); |
| 4206 } else if (expr->IsStringAccess()) { | 4183 } else if (expr->IsStringAccess()) { |
| 4207 CHECK_ALIVE(VisitForValue(expr->key())); | 4184 CHECK_ALIVE(VisitForValue(expr->key())); |
| 4208 HValue* index = Pop(); | 4185 HValue* index = Pop(); |
| 4209 HValue* string = Pop(); | 4186 HValue* string = Pop(); |
| (...skipping 2496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6706 } | 6683 } |
| 6707 } | 6684 } |
| 6708 | 6685 |
| 6709 #ifdef DEBUG | 6686 #ifdef DEBUG |
| 6710 if (graph_ != NULL) graph_->Verify(); | 6687 if (graph_ != NULL) graph_->Verify(); |
| 6711 if (allocator_ != NULL) allocator_->Verify(); | 6688 if (allocator_ != NULL) allocator_->Verify(); |
| 6712 #endif | 6689 #endif |
| 6713 } | 6690 } |
| 6714 | 6691 |
| 6715 } } // namespace v8::internal | 6692 } } // namespace v8::internal |
| OLD | NEW |