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

Side by Side Diff: src/hydrogen.cc

Issue 1266983002: VectorICs: Crankshaft adaptations to deal with vector store ics. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 4 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
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/hydrogen.h" 5 #include "src/hydrogen.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "src/v8.h" 9 #include "src/v8.h"
10 10
(...skipping 5739 matching lines...) Expand 10 before | Expand all | Expand 10 after
5750 5750
5751 Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral; 5751 Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
5752 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(), 5752 literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
5753 Runtime::FunctionForId(function_id), 5753 Runtime::FunctionForId(function_id),
5754 4); 5754 4);
5755 } 5755 }
5756 5756
5757 // The object is expected in the bailout environment during computation 5757 // The object is expected in the bailout environment during computation
5758 // of the property values and is the value of the entire expression. 5758 // of the property values and is the value of the entire expression.
5759 Push(literal); 5759 Push(literal);
5760 5760 int store_slot_index = 0;
5761 for (int i = 0; i < expr->properties()->length(); i++) { 5761 for (int i = 0; i < expr->properties()->length(); i++) {
5762 ObjectLiteral::Property* property = expr->properties()->at(i); 5762 ObjectLiteral::Property* property = expr->properties()->at(i);
5763 if (property->is_computed_name()) return Bailout(kComputedPropertyName); 5763 if (property->is_computed_name()) return Bailout(kComputedPropertyName);
5764 if (property->IsCompileTimeValue()) continue; 5764 if (property->IsCompileTimeValue()) continue;
5765 5765
5766 Literal* key = property->key()->AsLiteral(); 5766 Literal* key = property->key()->AsLiteral();
5767 Expression* value = property->value(); 5767 Expression* value = property->value();
5768 5768
5769 switch (property->kind()) { 5769 switch (property->kind()) {
5770 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 5770 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
5771 DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); 5771 DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
5772 // Fall through. 5772 // Fall through.
5773 case ObjectLiteral::Property::COMPUTED: 5773 case ObjectLiteral::Property::COMPUTED:
5774 // It is safe to use [[Put]] here because the boilerplate already 5774 // It is safe to use [[Put]] here because the boilerplate already
5775 // contains computed properties with an uninitialized value. 5775 // contains computed properties with an uninitialized value.
5776 if (key->value()->IsInternalizedString()) { 5776 if (key->value()->IsInternalizedString()) {
5777 if (property->emit_store()) { 5777 if (property->emit_store()) {
5778 CHECK_ALIVE(VisitForValue(value)); 5778 CHECK_ALIVE(VisitForValue(value));
5779 HValue* value = Pop(); 5779 HValue* value = Pop();
5780 5780
5781 // Add [[HomeObject]] to function literals.
5782 if (FunctionLiteral::NeedsHomeObject(property->value())) {
5783 Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
5784 HInstruction* store_home = BuildKeyedGeneric(
5785 STORE, NULL, value, Add<HConstant>(sym), literal);
5786 AddInstruction(store_home);
5787 DCHECK(store_home->HasObservableSideEffects());
5788 Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
5789 }
5790
5791 Handle<Map> map = property->GetReceiverType(); 5781 Handle<Map> map = property->GetReceiverType();
5792 Handle<String> name = key->AsPropertyName(); 5782 Handle<String> name = key->AsPropertyName();
5793 HValue* store; 5783 HValue* store;
5784 FeedbackVectorICSlot slot = expr->GetNthSlot(store_slot_index++);
5794 if (map.is_null()) { 5785 if (map.is_null()) {
5795 // If we don't know the monomorphic type, do a generic store. 5786 // If we don't know the monomorphic type, do a generic store.
5796 CHECK_ALIVE(store = BuildNamedGeneric( 5787 CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
5797 STORE, NULL, literal, name, value)); 5788 name, value));
5798 } else { 5789 } else {
5799 PropertyAccessInfo info(this, STORE, map, name); 5790 PropertyAccessInfo info(this, STORE, map, name);
5800 if (info.CanAccessMonomorphic()) { 5791 if (info.CanAccessMonomorphic()) {
5801 HValue* checked_literal = Add<HCheckMaps>(literal, map); 5792 HValue* checked_literal = Add<HCheckMaps>(literal, map);
5802 DCHECK(!info.IsAccessorConstant()); 5793 DCHECK(!info.IsAccessorConstant());
5803 store = BuildMonomorphicAccess( 5794 store = BuildMonomorphicAccess(
5804 &info, literal, checked_literal, value, 5795 &info, literal, checked_literal, value,
5805 BailoutId::None(), BailoutId::None()); 5796 BailoutId::None(), BailoutId::None());
5806 } else { 5797 } else {
5807 CHECK_ALIVE(store = BuildNamedGeneric( 5798 CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot,
5808 STORE, NULL, literal, name, value)); 5799 literal, name, value));
5809 } 5800 }
5810 } 5801 }
5811 if (store->IsInstruction()) { 5802 if (store->IsInstruction()) {
5812 AddInstruction(HInstruction::cast(store)); 5803 AddInstruction(HInstruction::cast(store));
5813 } 5804 }
5814 DCHECK(store->HasObservableSideEffects()); 5805 DCHECK(store->HasObservableSideEffects());
5815 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); 5806 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
5807
5808 // Add [[HomeObject]] to function literals.
5809 if (FunctionLiteral::NeedsHomeObject(property->value())) {
5810 Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
5811 HInstruction* store_home = BuildNamedGeneric(
5812 STORE, NULL, expr->GetNthSlot(store_slot_index++), value, sym,
5813 literal);
5814 AddInstruction(store_home);
5815 DCHECK(store_home->HasObservableSideEffects());
5816 Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
5817 }
5816 } else { 5818 } else {
5817 CHECK_ALIVE(VisitForEffect(value)); 5819 CHECK_ALIVE(VisitForEffect(value));
5818 } 5820 }
5819 break; 5821 break;
5820 } 5822 }
5821 // Fall through. 5823 // Fall through.
5822 case ObjectLiteral::Property::PROTOTYPE: 5824 case ObjectLiteral::Property::PROTOTYPE:
5823 case ObjectLiteral::Property::SETTER: 5825 case ObjectLiteral::Property::SETTER:
5824 case ObjectLiteral::Property::GETTER: 5826 case ObjectLiteral::Property::GETTER:
5825 return Bailout(kObjectLiteralWithComplexProperty); 5827 return Bailout(kObjectLiteralWithComplexProperty);
5826 default: UNREACHABLE(); 5828 default: UNREACHABLE();
5827 } 5829 }
5828 } 5830 }
5829 5831
5832 // Crankshaft may not consume all the slots because it doesn't emit accessors.
5833 DCHECK(!FLAG_vector_stores || store_slot_index <= expr->slot_count());
5834
5830 if (expr->has_function()) { 5835 if (expr->has_function()) {
5831 // Return the result of the transformation to fast properties 5836 // Return the result of the transformation to fast properties
5832 // instead of the original since this operation changes the map 5837 // instead of the original since this operation changes the map
5833 // of the object. This makes sure that the original object won't 5838 // of the object. This makes sure that the original object won't
5834 // be used by other optimized code before it is transformed 5839 // be used by other optimized code before it is transformed
5835 // (e.g. because of code motion). 5840 // (e.g. because of code motion).
5836 HToFastProperties* result = Add<HToFastProperties>(Pop()); 5841 HToFastProperties* result = Add<HToFastProperties>(Pop());
5837 return ast_context()->ReturnValue(result); 5842 return ast_context()->ReturnValue(result);
5838 } else { 5843 } else {
5839 return ast_context()->ReturnValue(Pop()); 5844 return ast_context()->ReturnValue(Pop());
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after
6454 DCHECK(info->IsDataConstant()); 6459 DCHECK(info->IsDataConstant());
6455 if (info->IsLoad()) { 6460 if (info->IsLoad()) {
6456 return New<HConstant>(info->constant()); 6461 return New<HConstant>(info->constant());
6457 } else { 6462 } else {
6458 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); 6463 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
6459 } 6464 }
6460 } 6465 }
6461 6466
6462 6467
6463 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( 6468 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
6464 PropertyAccessType access_type, Expression* expr, BailoutId ast_id, 6469 PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
6465 BailoutId return_id, HValue* object, HValue* value, SmallMapList* maps, 6470 BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
6466 Handle<String> name) { 6471 SmallMapList* maps, Handle<String> name) {
6467 // Something did not match; must use a polymorphic load. 6472 // Something did not match; must use a polymorphic load.
6468 int count = 0; 6473 int count = 0;
6469 HBasicBlock* join = NULL; 6474 HBasicBlock* join = NULL;
6470 HBasicBlock* number_block = NULL; 6475 HBasicBlock* number_block = NULL;
6471 bool handled_string = false; 6476 bool handled_string = false;
6472 6477
6473 bool handle_smi = false; 6478 bool handle_smi = false;
6474 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism); 6479 STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
6475 int i; 6480 int i;
6476 for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) { 6481 for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
6574 set_current_block(if_false); 6579 set_current_block(if_false);
6575 } 6580 }
6576 6581
6577 // Finish up. Unconditionally deoptimize if we've handled all the maps we 6582 // Finish up. Unconditionally deoptimize if we've handled all the maps we
6578 // know about and do not want to handle ones we've never seen. Otherwise 6583 // know about and do not want to handle ones we've never seen. Otherwise
6579 // use a generic IC. 6584 // use a generic IC.
6580 if (count == maps->length() && FLAG_deoptimize_uncommon_cases) { 6585 if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
6581 FinishExitWithHardDeoptimization( 6586 FinishExitWithHardDeoptimization(
6582 Deoptimizer::kUnknownMapInPolymorphicAccess); 6587 Deoptimizer::kUnknownMapInPolymorphicAccess);
6583 } else { 6588 } else {
6584 HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name, 6589 HInstruction* instr =
6585 value); 6590 BuildNamedGeneric(access_type, expr, slot, object, name, value);
6586 AddInstruction(instr); 6591 AddInstruction(instr);
6587 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); 6592 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
6588 6593
6589 if (join != NULL) { 6594 if (join != NULL) {
6590 Goto(join); 6595 Goto(join);
6591 } else { 6596 } else {
6592 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6597 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6593 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 6598 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6594 return; 6599 return;
6595 } 6600 }
(...skipping 27 matching lines...) Expand all
6623 6628
6624 6629
6625 static bool AreStringTypes(SmallMapList* maps) { 6630 static bool AreStringTypes(SmallMapList* maps) {
6626 for (int i = 0; i < maps->length(); i++) { 6631 for (int i = 0; i < maps->length(); i++) {
6627 if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false; 6632 if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
6628 } 6633 }
6629 return true; 6634 return true;
6630 } 6635 }
6631 6636
6632 6637
6633 void HOptimizedGraphBuilder::BuildStore(Expression* expr, 6638 void HOptimizedGraphBuilder::BuildStore(Expression* expr, Property* prop,
6634 Property* prop, 6639 FeedbackVectorICSlot slot,
6635 BailoutId ast_id, 6640 BailoutId ast_id, BailoutId return_id,
6636 BailoutId return_id,
6637 bool is_uninitialized) { 6641 bool is_uninitialized) {
6638 if (!prop->key()->IsPropertyName()) { 6642 if (!prop->key()->IsPropertyName()) {
6639 // Keyed store. 6643 // Keyed store.
6640 HValue* value = Pop(); 6644 HValue* value = Pop();
6641 HValue* key = Pop(); 6645 HValue* key = Pop();
6642 HValue* object = Pop(); 6646 HValue* object = Pop();
6643 bool has_side_effects = false; 6647 bool has_side_effects = false;
6644 HValue* result = HandleKeyedElementAccess( 6648 HValue* result =
6645 object, key, value, expr, ast_id, return_id, STORE, &has_side_effects); 6649 HandleKeyedElementAccess(object, key, value, expr, slot, ast_id,
6650 return_id, STORE, &has_side_effects);
6646 if (has_side_effects) { 6651 if (has_side_effects) {
6647 if (!ast_context()->IsEffect()) Push(value); 6652 if (!ast_context()->IsEffect()) Push(value);
6648 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6653 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6649 if (!ast_context()->IsEffect()) Drop(1); 6654 if (!ast_context()->IsEffect()) Drop(1);
6650 } 6655 }
6651 if (result == NULL) return; 6656 if (result == NULL) return;
6652 return ast_context()->ReturnValue(value); 6657 return ast_context()->ReturnValue(value);
6653 } 6658 }
6654 6659
6655 // Named store. 6660 // Named store.
6656 HValue* value = Pop(); 6661 HValue* value = Pop();
6657 HValue* object = Pop(); 6662 HValue* object = Pop();
6658 6663
6659 Literal* key = prop->key()->AsLiteral(); 6664 Literal* key = prop->key()->AsLiteral();
6660 Handle<String> name = Handle<String>::cast(key->value()); 6665 Handle<String> name = Handle<String>::cast(key->value());
6661 DCHECK(!name.is_null()); 6666 DCHECK(!name.is_null());
6662 6667
6663 HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, object, 6668 HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, slot,
6664 name, value, is_uninitialized); 6669 object, name, value, is_uninitialized);
6665 if (access == NULL) return; 6670 if (access == NULL) return;
6666 6671
6667 if (!ast_context()->IsEffect()) Push(value); 6672 if (!ast_context()->IsEffect()) Push(value);
6668 if (access->IsInstruction()) AddInstruction(HInstruction::cast(access)); 6673 if (access->IsInstruction()) AddInstruction(HInstruction::cast(access));
6669 if (access->HasObservableSideEffects()) { 6674 if (access->HasObservableSideEffects()) {
6670 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6675 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6671 } 6676 }
6672 if (!ast_context()->IsEffect()) Drop(1); 6677 if (!ast_context()->IsEffect()) Drop(1);
6673 return ast_context()->ReturnValue(value); 6678 return ast_context()->ReturnValue(value);
6674 } 6679 }
6675 6680
6676 6681
6677 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 6682 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
6678 Property* prop = expr->target()->AsProperty(); 6683 Property* prop = expr->target()->AsProperty();
6679 DCHECK(prop != NULL); 6684 DCHECK(prop != NULL);
6680 CHECK_ALIVE(VisitForValue(prop->obj())); 6685 CHECK_ALIVE(VisitForValue(prop->obj()));
6681 if (!prop->key()->IsPropertyName()) { 6686 if (!prop->key()->IsPropertyName()) {
6682 CHECK_ALIVE(VisitForValue(prop->key())); 6687 CHECK_ALIVE(VisitForValue(prop->key()));
6683 } 6688 }
6684 CHECK_ALIVE(VisitForValue(expr->value())); 6689 CHECK_ALIVE(VisitForValue(expr->value()));
6685 BuildStore(expr, prop, expr->id(), 6690 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
6686 expr->AssignmentId(), expr->IsUninitialized()); 6691 expr->AssignmentId(), expr->IsUninitialized());
6687 } 6692 }
6688 6693
6689 6694
6690 // Because not every expression has a position and there is not common 6695 // Because not every expression has a position and there is not common
6691 // superclass of Assignment and CountOperation, we cannot just pass the 6696 // superclass of Assignment and CountOperation, we cannot just pass the
6692 // owning expression instead of position and ast_id separately. 6697 // owning expression instead of position and ast_id separately.
6693 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( 6698 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
6694 Variable* var, 6699 Variable* var, HValue* value, FeedbackVectorICSlot ic_slot,
6695 HValue* value,
6696 BailoutId ast_id) { 6700 BailoutId ast_id) {
6697 Handle<GlobalObject> global(current_info()->global_object()); 6701 Handle<GlobalObject> global(current_info()->global_object());
6698 6702
6699 // Lookup in script contexts. 6703 // Lookup in script contexts.
6700 { 6704 {
6701 Handle<ScriptContextTable> script_contexts( 6705 Handle<ScriptContextTable> script_contexts(
6702 global->native_context()->script_context_table()); 6706 global->native_context()->script_context_table());
6703 ScriptContextTable::LookupResult lookup; 6707 ScriptContextTable::LookupResult lookup;
6704 if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) { 6708 if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
6705 if (lookup.mode == CONST) { 6709 if (lookup.mode == CONST) {
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
6793 DCHECK(instr->HasObservableSideEffects()); 6797 DCHECK(instr->HasObservableSideEffects());
6794 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6798 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6795 6799
6796 } else { 6800 } else {
6797 HValue* global_object = Add<HLoadNamedField>( 6801 HValue* global_object = Add<HLoadNamedField>(
6798 context(), nullptr, 6802 context(), nullptr,
6799 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); 6803 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
6800 HStoreNamedGeneric* instr = 6804 HStoreNamedGeneric* instr =
6801 Add<HStoreNamedGeneric>(global_object, var->name(), value, 6805 Add<HStoreNamedGeneric>(global_object, var->name(), value,
6802 function_language_mode(), PREMONOMORPHIC); 6806 function_language_mode(), PREMONOMORPHIC);
6807 if (FLAG_vector_stores) {
6808 Handle<TypeFeedbackVector> vector =
6809 handle(current_feedback_vector(), isolate());
6810 instr->SetVectorAndSlot(vector, ic_slot);
6811 }
6803 USE(instr); 6812 USE(instr);
6804 DCHECK(instr->HasObservableSideEffects()); 6813 DCHECK(instr->HasObservableSideEffects());
6805 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 6814 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
6806 } 6815 }
6807 } 6816 }
6808 6817
6809 6818
6810 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 6819 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
6811 Expression* target = expr->target(); 6820 Expression* target = expr->target();
6812 VariableProxy* proxy = target->AsVariableProxy(); 6821 VariableProxy* proxy = target->AsVariableProxy();
6813 Property* prop = target->AsProperty(); 6822 Property* prop = target->AsProperty();
6814 DCHECK(proxy == NULL || prop == NULL); 6823 DCHECK(proxy == NULL || prop == NULL);
6815 6824
6816 // We have a second position recorded in the FullCodeGenerator to have 6825 // We have a second position recorded in the FullCodeGenerator to have
6817 // type feedback for the binary operation. 6826 // type feedback for the binary operation.
6818 BinaryOperation* operation = expr->binary_operation(); 6827 BinaryOperation* operation = expr->binary_operation();
6819 6828
6820 if (proxy != NULL) { 6829 if (proxy != NULL) {
6821 Variable* var = proxy->var(); 6830 Variable* var = proxy->var();
6822 if (var->mode() == LET) { 6831 if (var->mode() == LET) {
6823 return Bailout(kUnsupportedLetCompoundAssignment); 6832 return Bailout(kUnsupportedLetCompoundAssignment);
6824 } 6833 }
6825 6834
6826 CHECK_ALIVE(VisitForValue(operation)); 6835 CHECK_ALIVE(VisitForValue(operation));
6827 6836
6828 switch (var->location()) { 6837 switch (var->location()) {
6829 case VariableLocation::GLOBAL: 6838 case VariableLocation::GLOBAL:
6830 case VariableLocation::UNALLOCATED: 6839 case VariableLocation::UNALLOCATED:
6831 HandleGlobalVariableAssignment(var, 6840 HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
6832 Top(),
6833 expr->AssignmentId()); 6841 expr->AssignmentId());
6834 break; 6842 break;
6835 6843
6836 case VariableLocation::PARAMETER: 6844 case VariableLocation::PARAMETER:
6837 case VariableLocation::LOCAL: 6845 case VariableLocation::LOCAL:
6838 if (var->mode() == CONST_LEGACY) { 6846 if (var->mode() == CONST_LEGACY) {
6839 return Bailout(kUnsupportedConstCompoundAssignment); 6847 return Bailout(kUnsupportedConstCompoundAssignment);
6840 } 6848 }
6841 if (var->mode() == CONST) { 6849 if (var->mode() == CONST) {
6842 return Bailout(kNonInitializerAssignmentToConst); 6850 return Bailout(kNonInitializerAssignmentToConst);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
6898 } 6906 }
6899 6907
6900 CHECK_ALIVE(PushLoad(prop, object, key)); 6908 CHECK_ALIVE(PushLoad(prop, object, key));
6901 6909
6902 CHECK_ALIVE(VisitForValue(expr->value())); 6910 CHECK_ALIVE(VisitForValue(expr->value()));
6903 HValue* right = Pop(); 6911 HValue* right = Pop();
6904 HValue* left = Pop(); 6912 HValue* left = Pop();
6905 6913
6906 Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE)); 6914 Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
6907 6915
6908 BuildStore(expr, prop, expr->id(), 6916 BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
6909 expr->AssignmentId(), expr->IsUninitialized()); 6917 expr->AssignmentId(), expr->IsUninitialized());
6910 } else { 6918 } else {
6911 return Bailout(kInvalidLhsInCompoundAssignment); 6919 return Bailout(kInvalidLhsInCompoundAssignment);
6912 } 6920 }
6913 } 6921 }
6914 6922
6915 6923
6916 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { 6924 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
6917 DCHECK(!HasStackOverflow()); 6925 DCHECK(!HasStackOverflow());
6918 DCHECK(current_block() != NULL); 6926 DCHECK(current_block() != NULL);
(...skipping 30 matching lines...) Expand all
6949 } 6957 }
6950 } 6958 }
6951 6959
6952 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments); 6960 if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
6953 6961
6954 // Handle the assignment. 6962 // Handle the assignment.
6955 switch (var->location()) { 6963 switch (var->location()) {
6956 case VariableLocation::GLOBAL: 6964 case VariableLocation::GLOBAL:
6957 case VariableLocation::UNALLOCATED: 6965 case VariableLocation::UNALLOCATED:
6958 CHECK_ALIVE(VisitForValue(expr->value())); 6966 CHECK_ALIVE(VisitForValue(expr->value()));
6959 HandleGlobalVariableAssignment(var, 6967 HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
6960 Top(),
6961 expr->AssignmentId()); 6968 expr->AssignmentId());
6962 return ast_context()->ReturnValue(Pop()); 6969 return ast_context()->ReturnValue(Pop());
6963 6970
6964 case VariableLocation::PARAMETER: 6971 case VariableLocation::PARAMETER:
6965 case VariableLocation::LOCAL: { 6972 case VariableLocation::LOCAL: {
6966 // Perform an initialization check for let declared variables 6973 // Perform an initialization check for let declared variables
6967 // or parameters. 6974 // or parameters.
6968 if (var->mode() == LET && expr->op() == Token::ASSIGN) { 6975 if (var->mode() == LET && expr->op() == Token::ASSIGN) {
6969 HValue* env_value = environment()->Lookup(var); 6976 HValue* env_value = environment()->Lookup(var);
6970 if (env_value == graph()->GetConstantHole()) { 6977 if (env_value == graph()->GetConstantHole()) {
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
7097 if (c_string->HasStringValue()) { 7104 if (c_string->HasStringValue()) {
7098 return New<HConstant>(c_string->StringValue()->length()); 7105 return New<HConstant>(c_string->StringValue()->length());
7099 } 7106 }
7100 } 7107 }
7101 return New<HLoadNamedField>(string, nullptr, 7108 return New<HLoadNamedField>(string, nullptr,
7102 HObjectAccess::ForStringLength()); 7109 HObjectAccess::ForStringLength());
7103 } 7110 }
7104 7111
7105 7112
7106 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( 7113 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
7107 PropertyAccessType access_type, Expression* expr, HValue* object, 7114 PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
7108 Handle<String> name, HValue* value, bool is_uninitialized) { 7115 HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) {
7109 if (is_uninitialized) { 7116 if (is_uninitialized) {
7110 Add<HDeoptimize>( 7117 Add<HDeoptimize>(
7111 Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess, 7118 Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess,
7112 Deoptimizer::SOFT); 7119 Deoptimizer::SOFT);
7113 } 7120 }
7114 if (access_type == LOAD) { 7121 if (access_type == LOAD) {
7115 Handle<TypeFeedbackVector> vector = 7122 Handle<TypeFeedbackVector> vector =
7116 handle(current_feedback_vector(), isolate()); 7123 handle(current_feedback_vector(), isolate());
7117 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot();
7118 7124
7119 if (!expr->AsProperty()->key()->IsPropertyName()) { 7125 if (!expr->AsProperty()->key()->IsPropertyName()) {
7120 // It's possible that a keyed load of a constant string was converted 7126 // It's possible that a keyed load of a constant string was converted
7121 // to a named load. Here, at the last minute, we need to make sure to 7127 // to a named load. Here, at the last minute, we need to make sure to
7122 // use a generic Keyed Load if we are using the type vector, because 7128 // use a generic Keyed Load if we are using the type vector, because
7123 // it has to share information with full code. 7129 // it has to share information with full code.
7124 HConstant* key = Add<HConstant>(name); 7130 HConstant* key = Add<HConstant>(name);
7125 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>( 7131 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
7126 object, key, function_language_mode(), PREMONOMORPHIC); 7132 object, key, function_language_mode(), PREMONOMORPHIC);
7127 result->SetVectorAndSlot(vector, slot); 7133 result->SetVectorAndSlot(vector, slot);
7128 return result; 7134 return result;
7129 } 7135 }
7130 7136
7131 HLoadNamedGeneric* result = New<HLoadNamedGeneric>( 7137 HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
7132 object, name, function_language_mode(), PREMONOMORPHIC); 7138 object, name, function_language_mode(), PREMONOMORPHIC);
7133 result->SetVectorAndSlot(vector, slot); 7139 result->SetVectorAndSlot(vector, slot);
7134 return result; 7140 return result;
7135 } else { 7141 } else {
7136 return New<HStoreNamedGeneric>(object, name, value, 7142 if (FLAG_vector_stores &&
7137 function_language_mode(), PREMONOMORPHIC); 7143 current_feedback_vector()->GetKind(slot) == Code::KEYED_STORE_IC) {
7144 // It's possible that a keyed store of a constant string was converted
7145 // to a named store. Here, at the last minute, we need to make sure to
7146 // use a generic Keyed Store if we are using the type vector, because
7147 // it has to share information with full code.
7148 HConstant* key = Add<HConstant>(name);
7149 HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
7150 object, key, value, function_language_mode(), PREMONOMORPHIC);
7151 Handle<TypeFeedbackVector> vector =
7152 handle(current_feedback_vector(), isolate());
7153 result->SetVectorAndSlot(vector, slot);
7154 return result;
7155 }
7156
7157 HStoreNamedGeneric* result = New<HStoreNamedGeneric>(
7158 object, name, value, function_language_mode(), PREMONOMORPHIC);
7159 if (FLAG_vector_stores) {
7160 Handle<TypeFeedbackVector> vector =
7161 handle(current_feedback_vector(), isolate());
7162 result->SetVectorAndSlot(vector, slot);
7163 }
7164 return result;
7138 } 7165 }
7139 } 7166 }
7140 7167
7141 7168
7142
7143 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric( 7169 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
7144 PropertyAccessType access_type, 7170 PropertyAccessType access_type, Expression* expr, FeedbackVectorICSlot slot,
7145 Expression* expr, 7171 HValue* object, HValue* key, HValue* value) {
7146 HValue* object,
7147 HValue* key,
7148 HValue* value) {
7149 if (access_type == LOAD) { 7172 if (access_type == LOAD) {
7150 InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState(); 7173 InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
7151 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>( 7174 HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
7152 object, key, function_language_mode(), initial_state); 7175 object, key, function_language_mode(), initial_state);
7153 // HLoadKeyedGeneric with vector ics benefits from being encoded as 7176 // HLoadKeyedGeneric with vector ics benefits from being encoded as
7154 // MEGAMORPHIC because the vector/slot combo becomes unnecessary. 7177 // MEGAMORPHIC because the vector/slot combo becomes unnecessary.
7155 if (initial_state != MEGAMORPHIC) { 7178 if (initial_state != MEGAMORPHIC) {
7156 // We need to pass vector information. 7179 // We need to pass vector information.
7157 Handle<TypeFeedbackVector> vector = 7180 Handle<TypeFeedbackVector> vector =
7158 handle(current_feedback_vector(), isolate()); 7181 handle(current_feedback_vector(), isolate());
7159 FeedbackVectorICSlot slot = expr->AsProperty()->PropertyFeedbackSlot();
7160 result->SetVectorAndSlot(vector, slot); 7182 result->SetVectorAndSlot(vector, slot);
7161 } 7183 }
7162 return result; 7184 return result;
7163 } else { 7185 } else {
7164 return New<HStoreKeyedGeneric>(object, key, value, function_language_mode(), 7186 HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
7165 PREMONOMORPHIC); 7187 object, key, value, function_language_mode(), PREMONOMORPHIC);
7188 if (FLAG_vector_stores) {
7189 Handle<TypeFeedbackVector> vector =
7190 handle(current_feedback_vector(), isolate());
7191 result->SetVectorAndSlot(vector, slot);
7192 }
7193 return result;
7166 } 7194 }
7167 } 7195 }
7168 7196
7169 7197
7170 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) { 7198 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
7171 // Loads from a "stock" fast holey double arrays can elide the hole check. 7199 // Loads from a "stock" fast holey double arrays can elide the hole check.
7172 // Loads from a "stock" fast holey array can convert the hole to undefined 7200 // Loads from a "stock" fast holey array can convert the hole to undefined
7173 // with impunity. 7201 // with impunity.
7174 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE; 7202 LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
7175 bool holey_double_elements = 7203 bool holey_double_elements =
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
7292 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( 7320 HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
7293 checked_object, key, val, 7321 checked_object, key, val,
7294 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, 7322 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
7295 consolidated_elements_kind, 7323 consolidated_elements_kind,
7296 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE); 7324 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
7297 return instr; 7325 return instr;
7298 } 7326 }
7299 7327
7300 7328
7301 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( 7329 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
7302 Expression* expr, 7330 Expression* expr, FeedbackVectorICSlot slot, HValue* object, HValue* key,
7303 HValue* object, 7331 HValue* val, SmallMapList* maps, PropertyAccessType access_type,
7304 HValue* key, 7332 KeyedAccessStoreMode store_mode, bool* has_side_effects) {
7305 HValue* val,
7306 SmallMapList* maps,
7307 PropertyAccessType access_type,
7308 KeyedAccessStoreMode store_mode,
7309 bool* has_side_effects) {
7310 *has_side_effects = false; 7333 *has_side_effects = false;
7311 BuildCheckHeapObject(object); 7334 BuildCheckHeapObject(object);
7312 7335
7313 if (access_type == LOAD) { 7336 if (access_type == LOAD) {
7314 HInstruction* consolidated_load = 7337 HInstruction* consolidated_load =
7315 TryBuildConsolidatedElementLoad(object, key, val, maps); 7338 TryBuildConsolidatedElementLoad(object, key, val, maps);
7316 if (consolidated_load != NULL) { 7339 if (consolidated_load != NULL) {
7317 *has_side_effects |= consolidated_load->HasObservableSideEffects(); 7340 *has_side_effects |= consolidated_load->HasObservableSideEffects();
7318 return consolidated_load; 7341 return consolidated_load;
7319 } 7342 }
7320 } 7343 }
7321 7344
7322 // Elements_kind transition support. 7345 // Elements_kind transition support.
7323 MapHandleList transition_target(maps->length()); 7346 MapHandleList transition_target(maps->length());
7324 // Collect possible transition targets. 7347 // Collect possible transition targets.
7325 MapHandleList possible_transitioned_maps(maps->length()); 7348 MapHandleList possible_transitioned_maps(maps->length());
7326 for (int i = 0; i < maps->length(); ++i) { 7349 for (int i = 0; i < maps->length(); ++i) {
7327 Handle<Map> map = maps->at(i); 7350 Handle<Map> map = maps->at(i);
7328 // Loads from strings or loads with a mix of string and non-string maps 7351 // Loads from strings or loads with a mix of string and non-string maps
7329 // shouldn't be handled polymorphically. 7352 // shouldn't be handled polymorphically.
7330 DCHECK(access_type != LOAD || !map->IsStringMap()); 7353 DCHECK(access_type != LOAD || !map->IsStringMap());
7331 ElementsKind elements_kind = map->elements_kind(); 7354 ElementsKind elements_kind = map->elements_kind();
7332 if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) && 7355 if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
7333 elements_kind != GetInitialFastElementsKind()) { 7356 elements_kind != GetInitialFastElementsKind()) {
7334 possible_transitioned_maps.Add(map); 7357 possible_transitioned_maps.Add(map);
7335 } 7358 }
7336 if (IsSloppyArgumentsElements(elements_kind)) { 7359 if (IsSloppyArgumentsElements(elements_kind)) {
7337 HInstruction* result = BuildKeyedGeneric(access_type, expr, object, key, 7360 HInstruction* result =
7338 val); 7361 BuildKeyedGeneric(access_type, expr, slot, object, key, val);
7339 *has_side_effects = result->HasObservableSideEffects(); 7362 *has_side_effects = result->HasObservableSideEffects();
7340 return AddInstruction(result); 7363 return AddInstruction(result);
7341 } 7364 }
7342 } 7365 }
7343 // Get transition target for each map (NULL == no transition). 7366 // Get transition target for each map (NULL == no transition).
7344 for (int i = 0; i < maps->length(); ++i) { 7367 for (int i = 0; i < maps->length(); ++i) {
7345 Handle<Map> map = maps->at(i); 7368 Handle<Map> map = maps->at(i);
7346 Handle<Map> transitioned_map = 7369 Handle<Map> transitioned_map =
7347 Map::FindTransitionedMap(map, &possible_transitioned_maps); 7370 Map::FindTransitionedMap(map, &possible_transitioned_maps);
7348 transition_target.Add(transitioned_map); 7371 transition_target.Add(transitioned_map);
(...skipping 15 matching lines...) Expand all
7364 } 7387 }
7365 } 7388 }
7366 7389
7367 // If only one map is left after transitioning, handle this case 7390 // If only one map is left after transitioning, handle this case
7368 // monomorphically. 7391 // monomorphically.
7369 DCHECK(untransitionable_maps.length() >= 1); 7392 DCHECK(untransitionable_maps.length() >= 1);
7370 if (untransitionable_maps.length() == 1) { 7393 if (untransitionable_maps.length() == 1) {
7371 Handle<Map> untransitionable_map = untransitionable_maps[0]; 7394 Handle<Map> untransitionable_map = untransitionable_maps[0];
7372 HInstruction* instr = NULL; 7395 HInstruction* instr = NULL;
7373 if (!CanInlineElementAccess(untransitionable_map)) { 7396 if (!CanInlineElementAccess(untransitionable_map)) {
7374 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, 7397 instr = AddInstruction(
7375 val)); 7398 BuildKeyedGeneric(access_type, expr, slot, object, key, val));
7376 } else { 7399 } else {
7377 instr = BuildMonomorphicElementAccess( 7400 instr = BuildMonomorphicElementAccess(
7378 object, key, val, transition, untransitionable_map, access_type, 7401 object, key, val, transition, untransitionable_map, access_type,
7379 store_mode); 7402 store_mode);
7380 } 7403 }
7381 *has_side_effects |= instr->HasObservableSideEffects(); 7404 *has_side_effects |= instr->HasObservableSideEffects();
7382 return access_type == STORE ? val : instr; 7405 return access_type == STORE ? val : instr;
7383 } 7406 }
7384 7407
7385 HBasicBlock* join = graph()->CreateBasicBlock(); 7408 HBasicBlock* join = graph()->CreateBasicBlock();
7386 7409
7387 for (int i = 0; i < untransitionable_maps.length(); ++i) { 7410 for (int i = 0; i < untransitionable_maps.length(); ++i) {
7388 Handle<Map> map = untransitionable_maps[i]; 7411 Handle<Map> map = untransitionable_maps[i];
7389 ElementsKind elements_kind = map->elements_kind(); 7412 ElementsKind elements_kind = map->elements_kind();
7390 HBasicBlock* this_map = graph()->CreateBasicBlock(); 7413 HBasicBlock* this_map = graph()->CreateBasicBlock();
7391 HBasicBlock* other_map = graph()->CreateBasicBlock(); 7414 HBasicBlock* other_map = graph()->CreateBasicBlock();
7392 HCompareMap* mapcompare = 7415 HCompareMap* mapcompare =
7393 New<HCompareMap>(object, map, this_map, other_map); 7416 New<HCompareMap>(object, map, this_map, other_map);
7394 FinishCurrentBlock(mapcompare); 7417 FinishCurrentBlock(mapcompare);
7395 7418
7396 set_current_block(this_map); 7419 set_current_block(this_map);
7397 HInstruction* access = NULL; 7420 HInstruction* access = NULL;
7398 if (!CanInlineElementAccess(map)) { 7421 if (!CanInlineElementAccess(map)) {
7399 access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key, 7422 access = AddInstruction(
7400 val)); 7423 BuildKeyedGeneric(access_type, expr, slot, object, key, val));
7401 } else { 7424 } else {
7402 DCHECK(IsFastElementsKind(elements_kind) || 7425 DCHECK(IsFastElementsKind(elements_kind) ||
7403 IsFixedTypedArrayElementsKind(elements_kind)); 7426 IsFixedTypedArrayElementsKind(elements_kind));
7404 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); 7427 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
7405 // Happily, mapcompare is a checked object. 7428 // Happily, mapcompare is a checked object.
7406 access = BuildUncheckedMonomorphicElementAccess( 7429 access = BuildUncheckedMonomorphicElementAccess(
7407 mapcompare, key, val, 7430 mapcompare, key, val,
7408 map->instance_type() == JS_ARRAY_TYPE, 7431 map->instance_type() == JS_ARRAY_TYPE,
7409 elements_kind, access_type, 7432 elements_kind, access_type,
7410 load_mode, 7433 load_mode,
(...skipping 18 matching lines...) Expand all
7429 // Deopt if none of the cases matched. 7452 // Deopt if none of the cases matched.
7430 NoObservableSideEffectsScope scope(this); 7453 NoObservableSideEffectsScope scope(this);
7431 FinishExitWithHardDeoptimization( 7454 FinishExitWithHardDeoptimization(
7432 Deoptimizer::kUnknownMapInPolymorphicElementAccess); 7455 Deoptimizer::kUnknownMapInPolymorphicElementAccess);
7433 set_current_block(join); 7456 set_current_block(join);
7434 return access_type == STORE ? val : Pop(); 7457 return access_type == STORE ? val : Pop();
7435 } 7458 }
7436 7459
7437 7460
7438 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( 7461 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
7439 HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id, 7462 HValue* obj, HValue* key, HValue* val, Expression* expr,
7440 BailoutId return_id, PropertyAccessType access_type, 7463 FeedbackVectorICSlot slot, BailoutId ast_id, BailoutId return_id,
7441 bool* has_side_effects) { 7464 PropertyAccessType access_type, bool* has_side_effects) {
7442 if (key->ActualValue()->IsConstant()) { 7465 if (key->ActualValue()->IsConstant()) {
7443 Handle<Object> constant = 7466 Handle<Object> constant =
7444 HConstant::cast(key->ActualValue())->handle(isolate()); 7467 HConstant::cast(key->ActualValue())->handle(isolate());
7445 uint32_t array_index; 7468 uint32_t array_index;
7446 if (constant->IsString() && 7469 if (constant->IsString() &&
7447 !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) { 7470 !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) {
7448 if (!constant->IsUniqueName()) { 7471 if (!constant->IsUniqueName()) {
7449 constant = isolate()->factory()->InternalizeString( 7472 constant = isolate()->factory()->InternalizeString(
7450 Handle<String>::cast(constant)); 7473 Handle<String>::cast(constant));
7451 } 7474 }
7452 HValue* access = 7475 HValue* access =
7453 BuildNamedAccess(access_type, ast_id, return_id, expr, obj, 7476 BuildNamedAccess(access_type, ast_id, return_id, expr, slot, obj,
7454 Handle<String>::cast(constant), val, false); 7477 Handle<String>::cast(constant), val, false);
7455 if (access == NULL || access->IsPhi() || 7478 if (access == NULL || access->IsPhi() ||
7456 HInstruction::cast(access)->IsLinked()) { 7479 HInstruction::cast(access)->IsLinked()) {
7457 *has_side_effects = false; 7480 *has_side_effects = false;
7458 } else { 7481 } else {
7459 HInstruction* instr = HInstruction::cast(access); 7482 HInstruction* instr = HInstruction::cast(access);
7460 AddInstruction(instr); 7483 AddInstruction(instr);
7461 *has_side_effects = instr->HasObservableSideEffects(); 7484 *has_side_effects = instr->HasObservableSideEffects();
7462 } 7485 }
7463 return access; 7486 return access;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
7502 if (current_map->IsStringMap()) { 7525 if (current_map->IsStringMap()) {
7503 force_generic = true; 7526 force_generic = true;
7504 break; 7527 break;
7505 } 7528 }
7506 } 7529 }
7507 } 7530 }
7508 7531
7509 if (monomorphic) { 7532 if (monomorphic) {
7510 Handle<Map> map = maps->first(); 7533 Handle<Map> map = maps->first();
7511 if (!CanInlineElementAccess(map)) { 7534 if (!CanInlineElementAccess(map)) {
7512 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, 7535 instr = AddInstruction(
7513 val)); 7536 BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
7514 } else { 7537 } else {
7515 BuildCheckHeapObject(obj); 7538 BuildCheckHeapObject(obj);
7516 instr = BuildMonomorphicElementAccess( 7539 instr = BuildMonomorphicElementAccess(
7517 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); 7540 obj, key, val, NULL, map, access_type, expr->GetStoreMode());
7518 } 7541 }
7519 } else if (!force_generic && (maps != NULL && !maps->is_empty())) { 7542 } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
7520 return HandlePolymorphicElementAccess(expr, obj, key, val, maps, 7543 return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps,
7521 access_type, expr->GetStoreMode(), 7544 access_type, expr->GetStoreMode(),
7522 has_side_effects); 7545 has_side_effects);
7523 } else { 7546 } else {
7524 if (access_type == STORE) { 7547 if (access_type == STORE) {
7525 if (expr->IsAssignment() && 7548 if (expr->IsAssignment() &&
7526 expr->AsAssignment()->HasNoTypeInformation()) { 7549 expr->AsAssignment()->HasNoTypeInformation()) {
7527 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore, 7550 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore,
7528 Deoptimizer::SOFT); 7551 Deoptimizer::SOFT);
7529 } 7552 }
7530 } else { 7553 } else {
7531 if (expr->AsProperty()->HasNoTypeInformation()) { 7554 if (expr->AsProperty()->HasNoTypeInformation()) {
7532 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad, 7555 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad,
7533 Deoptimizer::SOFT); 7556 Deoptimizer::SOFT);
7534 } 7557 }
7535 } 7558 }
7536 instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val)); 7559 instr = AddInstruction(
7560 BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
7537 } 7561 }
7538 *has_side_effects = instr->HasObservableSideEffects(); 7562 *has_side_effects = instr->HasObservableSideEffects();
7539 return instr; 7563 return instr;
7540 } 7564 }
7541 7565
7542 7566
7543 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() { 7567 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
7544 // Outermost function already has arguments on the stack. 7568 // Outermost function already has arguments on the stack.
7545 if (function_state()->outer() == NULL) return; 7569 if (function_state()->outer() == NULL) return;
7546 7570
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
7614 result = New<HAccessArgumentsAt>(elements, length, checked_key); 7638 result = New<HAccessArgumentsAt>(elements, length, checked_key);
7615 } 7639 }
7616 } 7640 }
7617 ast_context()->ReturnInstruction(result, expr->id()); 7641 ast_context()->ReturnInstruction(result, expr->id());
7618 return true; 7642 return true;
7619 } 7643 }
7620 7644
7621 7645
7622 HValue* HOptimizedGraphBuilder::BuildNamedAccess( 7646 HValue* HOptimizedGraphBuilder::BuildNamedAccess(
7623 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, 7647 PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
7624 Expression* expr, HValue* object, Handle<String> name, HValue* value, 7648 Expression* expr, FeedbackVectorICSlot slot, HValue* object,
7625 bool is_uninitialized) { 7649 Handle<String> name, HValue* value, bool is_uninitialized) {
7626 SmallMapList* maps; 7650 SmallMapList* maps;
7627 ComputeReceiverTypes(expr, object, &maps, zone()); 7651 ComputeReceiverTypes(expr, object, &maps, zone());
7628 DCHECK(maps != NULL); 7652 DCHECK(maps != NULL);
7629 7653
7630 if (maps->length() > 0) { 7654 if (maps->length() > 0) {
7631 PropertyAccessInfo info(this, access, maps->first(), name); 7655 PropertyAccessInfo info(this, access, maps->first(), name);
7632 if (!info.CanAccessAsMonomorphic(maps)) { 7656 if (!info.CanAccessAsMonomorphic(maps)) {
7633 HandlePolymorphicNamedFieldAccess(access, expr, ast_id, return_id, object, 7657 HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
7634 value, maps, name); 7658 object, value, maps, name);
7635 return NULL; 7659 return NULL;
7636 } 7660 }
7637 7661
7638 HValue* checked_object; 7662 HValue* checked_object;
7639 // Type::Number() is only supported by polymorphic load/call handling. 7663 // Type::Number() is only supported by polymorphic load/call handling.
7640 DCHECK(!info.IsNumberType()); 7664 DCHECK(!info.IsNumberType());
7641 BuildCheckHeapObject(object); 7665 BuildCheckHeapObject(object);
7642 if (AreStringTypes(maps)) { 7666 if (AreStringTypes(maps)) {
7643 checked_object = 7667 checked_object =
7644 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); 7668 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
7645 } else { 7669 } else {
7646 checked_object = Add<HCheckMaps>(object, maps); 7670 checked_object = Add<HCheckMaps>(object, maps);
7647 } 7671 }
7648 return BuildMonomorphicAccess( 7672 return BuildMonomorphicAccess(
7649 &info, object, checked_object, value, ast_id, return_id); 7673 &info, object, checked_object, value, ast_id, return_id);
7650 } 7674 }
7651 7675
7652 return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized); 7676 return BuildNamedGeneric(access, expr, slot, object, name, value,
7677 is_uninitialized);
7653 } 7678 }
7654 7679
7655 7680
7656 void HOptimizedGraphBuilder::PushLoad(Property* expr, 7681 void HOptimizedGraphBuilder::PushLoad(Property* expr,
7657 HValue* object, 7682 HValue* object,
7658 HValue* key) { 7683 HValue* key) {
7659 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 7684 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
7660 Push(object); 7685 Push(object);
7661 if (key != NULL) Push(key); 7686 if (key != NULL) Push(key);
7662 BuildLoad(expr, expr->LoadId()); 7687 BuildLoad(expr, expr->LoadId());
7663 } 7688 }
7664 7689
7665 7690
7666 void HOptimizedGraphBuilder::BuildLoad(Property* expr, 7691 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
7667 BailoutId ast_id) { 7692 BailoutId ast_id) {
7668 HInstruction* instr = NULL; 7693 HInstruction* instr = NULL;
7669 if (expr->IsStringAccess()) { 7694 if (expr->IsStringAccess()) {
7670 HValue* index = Pop(); 7695 HValue* index = Pop();
7671 HValue* string = Pop(); 7696 HValue* string = Pop();
7672 HInstruction* char_code = BuildStringCharCodeAt(string, index); 7697 HInstruction* char_code = BuildStringCharCodeAt(string, index);
7673 AddInstruction(char_code); 7698 AddInstruction(char_code);
7674 instr = NewUncasted<HStringCharFromCode>(char_code); 7699 instr = NewUncasted<HStringCharFromCode>(char_code);
7675 7700
7676 } else if (expr->key()->IsPropertyName()) { 7701 } else if (expr->key()->IsPropertyName()) {
7677 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 7702 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
7678 HValue* object = Pop(); 7703 HValue* object = Pop();
7679 7704
7680 HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr, object, 7705 HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
7681 name, NULL, expr->IsUninitialized()); 7706 expr->PropertyFeedbackSlot(), object, name,
7707 NULL, expr->IsUninitialized());
7682 if (value == NULL) return; 7708 if (value == NULL) return;
7683 if (value->IsPhi()) return ast_context()->ReturnValue(value); 7709 if (value->IsPhi()) return ast_context()->ReturnValue(value);
7684 instr = HInstruction::cast(value); 7710 instr = HInstruction::cast(value);
7685 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); 7711 if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
7686 7712
7687 } else { 7713 } else {
7688 HValue* key = Pop(); 7714 HValue* key = Pop();
7689 HValue* obj = Pop(); 7715 HValue* obj = Pop();
7690 7716
7691 bool has_side_effects = false; 7717 bool has_side_effects = false;
7692 HValue* load = HandleKeyedElementAccess( 7718 HValue* load = HandleKeyedElementAccess(
7693 obj, key, NULL, expr, ast_id, expr->LoadId(), LOAD, &has_side_effects); 7719 obj, key, NULL, expr, expr->PropertyFeedbackSlot(), ast_id,
7720 expr->LoadId(), LOAD, &has_side_effects);
7694 if (has_side_effects) { 7721 if (has_side_effects) {
7695 if (ast_context()->IsEffect()) { 7722 if (ast_context()->IsEffect()) {
7696 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 7723 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7697 } else { 7724 } else {
7698 Push(load); 7725 Push(load);
7699 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); 7726 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
7700 Drop(1); 7727 Drop(1);
7701 } 7728 }
7702 } 7729 }
7703 if (load == NULL) return; 7730 if (load == NULL) return;
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
7966 set_current_block(if_false); 7993 set_current_block(if_false);
7967 } 7994 }
7968 7995
7969 // Finish up. Unconditionally deoptimize if we've handled all the maps we 7996 // Finish up. Unconditionally deoptimize if we've handled all the maps we
7970 // know about and do not want to handle ones we've never seen. Otherwise 7997 // know about and do not want to handle ones we've never seen. Otherwise
7971 // use a generic IC. 7998 // use a generic IC.
7972 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { 7999 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
7973 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); 8000 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall);
7974 } else { 8001 } else {
7975 Property* prop = expr->expression()->AsProperty(); 8002 Property* prop = expr->expression()->AsProperty();
7976 HInstruction* function = BuildNamedGeneric( 8003 HInstruction* function =
7977 LOAD, prop, receiver, name, NULL, prop->IsUninitialized()); 8004 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver,
8005 name, NULL, prop->IsUninitialized());
7978 AddInstruction(function); 8006 AddInstruction(function);
7979 Push(function); 8007 Push(function);
7980 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); 8008 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
7981 8009
7982 environment()->SetExpressionStackAt(1, function); 8010 environment()->SetExpressionStackAt(1, function);
7983 environment()->SetExpressionStackAt(0, receiver); 8011 environment()->SetExpressionStackAt(0, receiver);
7984 CHECK_ALIVE(VisitExpressions(expr->arguments())); 8012 CHECK_ALIVE(VisitExpressions(expr->arguments()));
7985 8013
7986 CallFunctionFlags flags = receiver->type().IsJSObject() 8014 CallFunctionFlags flags = receiver->type().IsJSObject()
7987 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; 8015 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
(...skipping 2436 matching lines...) Expand 10 before | Expand all | Expand 10 after
10424 if (!is_strong(function_language_mode())) { 10452 if (!is_strong(function_language_mode())) {
10425 instr->ClearAllSideEffects(); 10453 instr->ClearAllSideEffects();
10426 } else { 10454 } else {
10427 Add<HSimulate>(expr->ToNumberId(), REMOVABLE_SIMULATE); 10455 Add<HSimulate>(expr->ToNumberId(), REMOVABLE_SIMULATE);
10428 } 10456 }
10429 instr->SetFlag(HInstruction::kCannotBeTagged); 10457 instr->SetFlag(HInstruction::kCannotBeTagged);
10430 return instr; 10458 return instr;
10431 } 10459 }
10432 10460
10433 10461
10434 void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr, 10462 void HOptimizedGraphBuilder::BuildStoreForEffect(
10435 Property* prop, 10463 Expression* expr, Property* prop, FeedbackVectorICSlot slot,
10436 BailoutId ast_id, 10464 BailoutId ast_id, BailoutId return_id, HValue* object, HValue* key,
10437 BailoutId return_id, 10465 HValue* value) {
10438 HValue* object,
10439 HValue* key,
10440 HValue* value) {
10441 EffectContext for_effect(this); 10466 EffectContext for_effect(this);
10442 Push(object); 10467 Push(object);
10443 if (key != NULL) Push(key); 10468 if (key != NULL) Push(key);
10444 Push(value); 10469 Push(value);
10445 BuildStore(expr, prop, ast_id, return_id); 10470 BuildStore(expr, prop, slot, ast_id, return_id);
10446 } 10471 }
10447 10472
10448 10473
10449 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { 10474 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
10450 DCHECK(!HasStackOverflow()); 10475 DCHECK(!HasStackOverflow());
10451 DCHECK(current_block() != NULL); 10476 DCHECK(current_block() != NULL);
10452 DCHECK(current_block()->HasPredecessor()); 10477 DCHECK(current_block()->HasPredecessor());
10453 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); 10478 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
10454 Expression* target = expr->expression(); 10479 Expression* target = expr->expression();
10455 VariableProxy* proxy = target->AsVariableProxy(); 10480 VariableProxy* proxy = target->AsVariableProxy();
(...skipping 22 matching lines...) Expand all
10478 DCHECK(prop == NULL); 10503 DCHECK(prop == NULL);
10479 CHECK_ALIVE(VisitForValue(target)); 10504 CHECK_ALIVE(VisitForValue(target));
10480 10505
10481 after = BuildIncrement(returns_original_input, expr); 10506 after = BuildIncrement(returns_original_input, expr);
10482 input = returns_original_input ? Top() : Pop(); 10507 input = returns_original_input ? Top() : Pop();
10483 Push(after); 10508 Push(after);
10484 10509
10485 switch (var->location()) { 10510 switch (var->location()) {
10486 case VariableLocation::GLOBAL: 10511 case VariableLocation::GLOBAL:
10487 case VariableLocation::UNALLOCATED: 10512 case VariableLocation::UNALLOCATED:
10488 HandleGlobalVariableAssignment(var, 10513 HandleGlobalVariableAssignment(var, after, expr->CountSlot(),
10489 after,
10490 expr->AssignmentId()); 10514 expr->AssignmentId());
10491 break; 10515 break;
10492 10516
10493 case VariableLocation::PARAMETER: 10517 case VariableLocation::PARAMETER:
10494 case VariableLocation::LOCAL: 10518 case VariableLocation::LOCAL:
10495 BindIfLive(var, after); 10519 BindIfLive(var, after);
10496 break; 10520 break;
10497 10521
10498 case VariableLocation::CONTEXT: { 10522 case VariableLocation::CONTEXT: {
10499 // Bail out if we try to mutate a parameter value in a function 10523 // Bail out if we try to mutate a parameter value in a function
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
10545 10569
10546 CHECK_ALIVE(PushLoad(prop, object, key)); 10570 CHECK_ALIVE(PushLoad(prop, object, key));
10547 10571
10548 after = BuildIncrement(returns_original_input, expr); 10572 after = BuildIncrement(returns_original_input, expr);
10549 10573
10550 if (returns_original_input) { 10574 if (returns_original_input) {
10551 input = Pop(); 10575 input = Pop();
10552 // Drop object and key to push it again in the effect context below. 10576 // Drop object and key to push it again in the effect context below.
10553 Drop(key == NULL ? 1 : 2); 10577 Drop(key == NULL ? 1 : 2);
10554 environment()->SetExpressionStackAt(0, input); 10578 environment()->SetExpressionStackAt(0, input);
10555 CHECK_ALIVE(BuildStoreForEffect( 10579 CHECK_ALIVE(BuildStoreForEffect(expr, prop, expr->CountSlot(), expr->id(),
10556 expr, prop, expr->id(), expr->AssignmentId(), object, key, after)); 10580 expr->AssignmentId(), object, key, after));
10557 return ast_context()->ReturnValue(Pop()); 10581 return ast_context()->ReturnValue(Pop());
10558 } 10582 }
10559 10583
10560 environment()->SetExpressionStackAt(0, after); 10584 environment()->SetExpressionStackAt(0, after);
10561 return BuildStore(expr, prop, expr->id(), expr->AssignmentId()); 10585 return BuildStore(expr, prop, expr->CountSlot(), expr->id(),
10586 expr->AssignmentId());
10562 } 10587 }
10563 10588
10564 10589
10565 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( 10590 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
10566 HValue* string, 10591 HValue* string,
10567 HValue* index) { 10592 HValue* index) {
10568 if (string->IsConstant() && index->IsConstant()) { 10593 if (string->IsConstant() && index->IsConstant()) {
10569 HConstant* c_string = HConstant::cast(string); 10594 HConstant* c_string = HConstant::cast(string);
10570 HConstant* c_index = HConstant::cast(index); 10595 HConstant* c_index = HConstant::cast(index);
10571 if (c_string->HasStringValue() && c_index->HasNumberValue()) { 10596 if (c_string->HasStringValue() && c_index->HasNumberValue()) {
(...skipping 2748 matching lines...) Expand 10 before | Expand all | Expand 10 after
13320 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 13345 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
13321 } 13346 }
13322 13347
13323 #ifdef DEBUG 13348 #ifdef DEBUG
13324 graph_->Verify(false); // No full verify. 13349 graph_->Verify(false); // No full verify.
13325 #endif 13350 #endif
13326 } 13351 }
13327 13352
13328 } // namespace internal 13353 } // namespace internal
13329 } // namespace v8 13354 } // namespace v8
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698