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 3246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3257 // If the subexpression is a literal or a simple materialized literal it | 3257 // If the subexpression is a literal or a simple materialized literal it |
3258 // is already set in the cloned array. | 3258 // is already set in the cloned array. |
3259 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 3259 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
3260 | 3260 |
3261 CHECK_ALIVE(VisitForValue(subexpr)); | 3261 CHECK_ALIVE(VisitForValue(subexpr)); |
3262 HValue* value = Pop(); | 3262 HValue* value = Pop(); |
3263 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); | 3263 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); |
3264 | 3264 |
3265 // Load the elements array before the first store. | 3265 // Load the elements array before the first store. |
3266 if (elements == NULL) { | 3266 if (elements == NULL) { |
3267 elements = new(zone()) HLoadElements(literal); | 3267 elements = new(zone()) HLoadElements(literal, literal); |
Kevin Millikin (Chromium)
2011/07/11 15:03:54
The second occurrence of literal is used as a toke
Jakob Kummerow
2011/07/19 14:55:44
Obsolete (I undid the changes to HLoadElements).
| |
3268 AddInstruction(elements); | 3268 AddInstruction(elements); |
3269 } | 3269 } |
3270 | 3270 |
3271 HValue* key = AddInstruction( | 3271 HValue* key = AddInstruction( |
3272 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), | 3272 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), |
3273 Representation::Integer32())); | 3273 Representation::Integer32())); |
3274 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); | 3274 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); |
3275 AddSimulate(expr->GetIdForElement(i)); | 3275 AddSimulate(expr->GetIdForElement(i)); |
3276 } | 3276 } |
3277 return ast_context()->ReturnValue(Pop()); | 3277 return ast_context()->ReturnValue(Pop()); |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3888 HValue* val, | 3888 HValue* val, |
3889 Expression* expr, | 3889 Expression* expr, |
3890 bool is_store) { | 3890 bool is_store) { |
3891 ASSERT(expr->IsMonomorphic()); | 3891 ASSERT(expr->IsMonomorphic()); |
3892 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3892 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
3893 if (!map->has_fast_elements() && !map->has_external_array_elements()) { | 3893 if (!map->has_fast_elements() && !map->has_external_array_elements()) { |
3894 return is_store ? BuildStoreKeyedGeneric(object, key, val) | 3894 return is_store ? BuildStoreKeyedGeneric(object, key, val) |
3895 : BuildLoadKeyedGeneric(object, key); | 3895 : BuildLoadKeyedGeneric(object, key); |
3896 } | 3896 } |
3897 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3897 AddInstruction(new(zone()) HCheckNonSmi(object)); |
3898 AddInstruction(new(zone()) HCheckMap(object, map)); | 3898 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); |
3899 HInstruction* elements = new(zone()) HLoadElements(object); | 3899 HInstruction* elements = new(zone()) HLoadElements(object, mapcheck); |
3900 HInstruction* length = NULL; | 3900 HInstruction* length = NULL; |
3901 HInstruction* checked_key = NULL; | 3901 HInstruction* checked_key = NULL; |
3902 if (map->has_external_array_elements()) { | 3902 if (map->has_external_array_elements()) { |
3903 AddInstruction(elements); | 3903 AddInstruction(elements); |
3904 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3904 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); |
3905 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3905 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3906 HLoadExternalArrayPointer* external_elements = | 3906 HLoadExternalArrayPointer* external_elements = |
3907 new(zone()) HLoadExternalArrayPointer(elements); | 3907 new(zone()) HLoadExternalArrayPointer(elements); |
3908 AddInstruction(external_elements); | 3908 AddInstruction(external_elements); |
3909 return BuildExternalArrayElementAccess(external_elements, checked_key, | 3909 return BuildExternalArrayElementAccess(external_elements, checked_key, |
3910 val, map->elements_kind(), is_store); | 3910 val, map->elements_kind(), is_store); |
3911 } | 3911 } |
3912 ASSERT(map->has_fast_elements()); | 3912 ASSERT(map->has_fast_elements()); |
3913 if (map->instance_type() == JS_ARRAY_TYPE) { | 3913 if (map->instance_type() == JS_ARRAY_TYPE) { |
3914 length = AddInstruction(new(zone()) HJSArrayLength(object)); | 3914 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck)); |
3915 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3915 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3916 AddInstruction(elements); | 3916 AddInstruction(elements); |
3917 } else { | 3917 } else { |
3918 AddInstruction(elements); | 3918 AddInstruction(elements); |
3919 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 3919 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
3920 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3920 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3921 } | 3921 } |
3922 if (is_store) { | 3922 if (is_store) { |
3923 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); | 3923 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); |
3924 } else { | 3924 } else { |
(...skipping 30 matching lines...) Expand all Loading... | |
3955 todo_external_array = true; | 3955 todo_external_array = true; |
3956 } | 3956 } |
3957 } | 3957 } |
3958 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt. | 3958 // Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt. |
3959 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false; | 3959 type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false; |
3960 | 3960 |
3961 HBasicBlock* join = graph()->CreateBasicBlock(); | 3961 HBasicBlock* join = graph()->CreateBasicBlock(); |
3962 | 3962 |
3963 HInstruction* elements_kind_instr = | 3963 HInstruction* elements_kind_instr = |
3964 AddInstruction(new(zone()) HElementsKind(object)); | 3964 AddInstruction(new(zone()) HElementsKind(object)); |
3965 HCompareConstantEqAndBranch* elements_kind_branch = NULL; | |
3965 HInstruction* elements = NULL; | 3966 HInstruction* elements = NULL; |
3966 HLoadExternalArrayPointer* external_elements = NULL; | 3967 HLoadExternalArrayPointer* external_elements = NULL; |
3967 HInstruction* checked_key = NULL; | 3968 HInstruction* checked_key = NULL; |
3968 | 3969 |
3969 // FAST_ELEMENTS is assumed to be the first case. | 3970 // FAST_ELEMENTS is assumed to be the first case. |
3970 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0); | 3971 STATIC_ASSERT(JSObject::FAST_ELEMENTS == 0); |
3971 | 3972 |
3972 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; | 3973 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; |
3973 elements_kind <= JSObject::LAST_ELEMENTS_KIND; | 3974 elements_kind <= JSObject::LAST_ELEMENTS_KIND; |
3974 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { | 3975 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { |
3975 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we | 3976 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we |
3976 // need to add some code that's executed for all external array cases. | 3977 // need to add some code that's executed for all external array cases. |
3977 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 3978 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
3978 JSObject::LAST_ELEMENTS_KIND); | 3979 JSObject::LAST_ELEMENTS_KIND); |
3979 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 3980 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
3980 && todo_external_array) { | 3981 && todo_external_array) { |
3981 elements = AddInstruction(new(zone()) HLoadElements(object)); | 3982 elements = AddInstruction( |
3982 // We need to forcibly prevent some ElementsKind-dependent instructions | 3983 new(zone()) HLoadElements(object, elements_kind_branch)); |
Kevin Millikin (Chromium)
2011/07/11 15:03:54
Should we assert the check instruction is not NULL
Jakob Kummerow
2011/07/19 14:55:44
Good catch! Depending on the JS code being execute
| |
3983 // from being hoisted out of any loops they might occur in, because | |
3984 // the current loop-invariant-code-motion algorithm isn't clever enough | |
3985 // to deal with them properly. | |
3986 // There's some performance to be gained by developing a smarter | |
3987 // solution for this. | |
3988 elements->ClearFlag(HValue::kUseGVN); | |
3989 HInstruction* length = | 3984 HInstruction* length = |
3990 AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3985 AddInstruction(new(zone()) HExternalArrayLength(elements)); |
3991 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3986 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
3992 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 3987 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
3993 AddInstruction(external_elements); | 3988 AddInstruction(external_elements); |
3994 } | 3989 } |
3995 if (type_todo[elements_kind]) { | 3990 if (type_todo[elements_kind]) { |
3996 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 3991 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
3997 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 3992 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
3998 HCompareConstantEqAndBranch* compare = | 3993 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( |
3999 new(zone()) HCompareConstantEqAndBranch(elements_kind_instr, | 3994 elements_kind_instr, elements_kind, Token::EQ_STRICT); |
4000 elements_kind, | 3995 elements_kind_branch->SetSuccessorAt(0, if_true); |
4001 Token::EQ_STRICT); | 3996 elements_kind_branch->SetSuccessorAt(1, if_false); |
4002 compare->SetSuccessorAt(0, if_true); | 3997 current_block()->Finish(elements_kind_branch); |
4003 compare->SetSuccessorAt(1, if_false); | |
4004 current_block()->Finish(compare); | |
4005 | 3998 |
4006 set_current_block(if_true); | 3999 set_current_block(if_true); |
4007 HInstruction* access; | 4000 HInstruction* access; |
4008 if (elements_kind == JSObject::FAST_ELEMENTS) { | 4001 if (elements_kind == JSObject::FAST_ELEMENTS) { |
4009 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); | 4002 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); |
4010 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); | 4003 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); |
4011 HHasInstanceTypeAndBranch* typecheck = | 4004 HHasInstanceTypeAndBranch* typecheck = |
4012 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); | 4005 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); |
4013 typecheck->SetSuccessorAt(0, if_jsarray); | 4006 typecheck->SetSuccessorAt(0, if_jsarray); |
4014 typecheck->SetSuccessorAt(1, if_fastobject); | 4007 typecheck->SetSuccessorAt(1, if_fastobject); |
4015 current_block()->Finish(typecheck); | 4008 current_block()->Finish(typecheck); |
4016 | 4009 |
4017 set_current_block(if_jsarray); | 4010 set_current_block(if_jsarray); |
4018 HInstruction* length = new(zone()) HJSArrayLength(object); | 4011 HInstruction* length = new(zone()) HJSArrayLength(object, typecheck); |
4019 AddInstruction(length); | 4012 AddInstruction(length); |
4020 length->ClearFlag(HValue::kUseGVN); | |
4021 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4013 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4022 elements = AddInstruction(new(zone()) HLoadElements(object)); | 4014 elements = |
4023 elements->ClearFlag(HValue::kUseGVN); | 4015 AddInstruction(new(zone()) HLoadElements(object, checked_key)); |
4024 if (is_store) { | 4016 if (is_store) { |
4025 access = AddInstruction( | 4017 access = AddInstruction( |
4026 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4018 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
4027 } else { | 4019 } else { |
4028 access = AddInstruction( | 4020 access = AddInstruction( |
4029 new(zone()) HLoadKeyedFastElement(elements, checked_key)); | 4021 new(zone()) HLoadKeyedFastElement(elements, checked_key)); |
4030 Push(access); | 4022 Push(access); |
4031 } | 4023 } |
4032 *has_side_effects |= access->HasSideEffects(); | 4024 *has_side_effects |= access->HasSideEffects(); |
4033 if (position != -1) { | 4025 if (position != -1) { |
4034 access->set_position(position); | 4026 access->set_position(position); |
4035 } | 4027 } |
4036 if_jsarray->Goto(join); | 4028 if_jsarray->Goto(join); |
4037 | 4029 |
4038 set_current_block(if_fastobject); | 4030 set_current_block(if_fastobject); |
4039 elements = AddInstruction(new(zone()) HLoadElements(object)); | 4031 elements = AddInstruction(new(zone()) HLoadElements(object, typecheck)); |
4040 elements->ClearFlag(HValue::kUseGVN); | |
4041 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 4032 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
4042 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4033 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
4043 if (is_store) { | 4034 if (is_store) { |
4044 access = AddInstruction( | 4035 access = AddInstruction( |
4045 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4036 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
4046 } else { | 4037 } else { |
4047 access = AddInstruction( | 4038 access = AddInstruction( |
4048 new(zone()) HLoadKeyedFastElement(elements, checked_key)); | 4039 new(zone()) HLoadKeyedFastElement(elements, checked_key)); |
4049 } | 4040 } |
4050 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { | 4041 } else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) { |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4163 expr->RecordTypeFeedback(oracle()); | 4154 expr->RecordTypeFeedback(oracle()); |
4164 | 4155 |
4165 if (TryArgumentsAccess(expr)) return; | 4156 if (TryArgumentsAccess(expr)) return; |
4166 | 4157 |
4167 CHECK_ALIVE(VisitForValue(expr->obj())); | 4158 CHECK_ALIVE(VisitForValue(expr->obj())); |
4168 | 4159 |
4169 HInstruction* instr = NULL; | 4160 HInstruction* instr = NULL; |
4170 if (expr->IsArrayLength()) { | 4161 if (expr->IsArrayLength()) { |
4171 HValue* array = Pop(); | 4162 HValue* array = Pop(); |
4172 AddInstruction(new(zone()) HCheckNonSmi(array)); | 4163 AddInstruction(new(zone()) HCheckNonSmi(array)); |
4173 AddInstruction(HCheckInstanceType::NewIsJSArray(array)); | 4164 HInstruction* mapcheck = |
4174 instr = new(zone()) HJSArrayLength(array); | 4165 AddInstruction(HCheckInstanceType::NewIsJSArray(array)); |
4166 instr = new(zone()) HJSArrayLength(array, mapcheck); | |
4175 | 4167 |
4176 } else if (expr->IsStringLength()) { | 4168 } else if (expr->IsStringLength()) { |
4177 HValue* string = Pop(); | 4169 HValue* string = Pop(); |
4178 AddInstruction(new(zone()) HCheckNonSmi(string)); | 4170 AddInstruction(new(zone()) HCheckNonSmi(string)); |
4179 AddInstruction(HCheckInstanceType::NewIsString(string)); | 4171 AddInstruction(HCheckInstanceType::NewIsString(string)); |
4180 instr = new(zone()) HStringLength(string); | 4172 instr = new(zone()) HStringLength(string); |
4181 } else if (expr->IsStringAccess()) { | 4173 } else if (expr->IsStringAccess()) { |
4182 CHECK_ALIVE(VisitForValue(expr->key())); | 4174 CHECK_ALIVE(VisitForValue(expr->key())); |
4183 HValue* index = Pop(); | 4175 HValue* index = Pop(); |
4184 HValue* string = Pop(); | 4176 HValue* string = Pop(); |
(...skipping 2471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6656 } | 6648 } |
6657 } | 6649 } |
6658 | 6650 |
6659 #ifdef DEBUG | 6651 #ifdef DEBUG |
6660 if (graph_ != NULL) graph_->Verify(); | 6652 if (graph_ != NULL) graph_->Verify(); |
6661 if (allocator_ != NULL) allocator_->Verify(); | 6653 if (allocator_ != NULL) allocator_->Verify(); |
6662 #endif | 6654 #endif |
6663 } | 6655 } |
6664 | 6656 |
6665 } } // namespace v8::internal | 6657 } } // namespace v8::internal |
OLD | NEW |