Chromium Code Reviews| 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 |