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

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: rebase; handle HLoadElements differently 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') | no next file with comments »
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 3256 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698