Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: src/hydrogen.cc

Issue 7298003: Add fake data dependencies (instead of disabling GVN) to fix code motion (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: stricter instruction ordering Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/hydrogen-instructions.h » ('j') | src/hydrogen-instructions.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/hydrogen-instructions.h » ('j') | src/hydrogen-instructions.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698