| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 VariableProxy* var_proxy = AsVariableProxy(); | 75 VariableProxy* var_proxy = AsVariableProxy(); |
| 76 if (var_proxy == NULL) return false; | 76 if (var_proxy == NULL) return false; |
| 77 Variable* var = var_proxy->var(); | 77 Variable* var = var_proxy->var(); |
| 78 // The global identifier "undefined" is immutable. Everything | 78 // The global identifier "undefined" is immutable. Everything |
| 79 // else could be reassigned. | 79 // else could be reassigned. |
| 80 return var != NULL && var->location() == Variable::UNALLOCATED && | 80 return var != NULL && var->location() == Variable::UNALLOCATED && |
| 81 var_proxy->name()->Equals(isolate->heap()->undefined_string()); | 81 var_proxy->name()->Equals(isolate->heap()->undefined_string()); |
| 82 } | 82 } |
| 83 | 83 |
| 84 | 84 |
| 85 VariableProxy::VariableProxy(Isolate* isolate, Variable* var, int position) | 85 VariableProxy::VariableProxy(Zone* zone, Variable* var, int position) |
| 86 : Expression(isolate, position), | 86 : Expression(zone, position), |
| 87 name_(var->name()), | 87 name_(var->name()), |
| 88 var_(NULL), // Will be set by the call to BindTo. | 88 var_(NULL), // Will be set by the call to BindTo. |
| 89 is_this_(var->is_this()), | 89 is_this_(var->is_this()), |
| 90 is_trivial_(false), | 90 is_trivial_(false), |
| 91 is_lvalue_(false), | 91 is_lvalue_(false), |
| 92 interface_(var->interface()) { | 92 interface_(var->interface()) { |
| 93 BindTo(var); | 93 BindTo(var); |
| 94 } | 94 } |
| 95 | 95 |
| 96 | 96 |
| 97 VariableProxy::VariableProxy(Isolate* isolate, | 97 VariableProxy::VariableProxy(Zone* zone, |
| 98 Handle<String> name, | 98 Handle<String> name, |
| 99 bool is_this, | 99 bool is_this, |
| 100 Interface* interface, | 100 Interface* interface, |
| 101 int position) | 101 int position) |
| 102 : Expression(isolate, position), | 102 : Expression(zone, position), |
| 103 name_(name), | 103 name_(name), |
| 104 var_(NULL), | 104 var_(NULL), |
| 105 is_this_(is_this), | 105 is_this_(is_this), |
| 106 is_trivial_(false), | 106 is_trivial_(false), |
| 107 is_lvalue_(false), | 107 is_lvalue_(false), |
| 108 interface_(interface) { | 108 interface_(interface) { |
| 109 // Names must be canonicalized for fast equality checks. | 109 // Names must be canonicalized for fast equality checks. |
| 110 ASSERT(name->IsInternalizedString()); | 110 ASSERT(name->IsInternalizedString()); |
| 111 } | 111 } |
| 112 | 112 |
| 113 | 113 |
| 114 void VariableProxy::BindTo(Variable* var) { | 114 void VariableProxy::BindTo(Variable* var) { |
| 115 ASSERT(var_ == NULL); // must be bound only once | 115 ASSERT(var_ == NULL); // must be bound only once |
| 116 ASSERT(var != NULL); // must bind | 116 ASSERT(var != NULL); // must bind |
| 117 ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface())); | 117 ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface())); |
| 118 ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name())); | 118 ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name())); |
| 119 // Ideally CONST-ness should match. However, this is very hard to achieve | 119 // Ideally CONST-ness should match. However, this is very hard to achieve |
| 120 // because we don't know the exact semantics of conflicting (const and | 120 // because we don't know the exact semantics of conflicting (const and |
| 121 // non-const) multiple variable declarations, const vars introduced via | 121 // non-const) multiple variable declarations, const vars introduced via |
| 122 // eval() etc. Const-ness and variable declarations are a complete mess | 122 // eval() etc. Const-ness and variable declarations are a complete mess |
| 123 // in JS. Sigh... | 123 // in JS. Sigh... |
| 124 var_ = var; | 124 var_ = var; |
| 125 var->set_is_used(true); | 125 var->set_is_used(true); |
| 126 } | 126 } |
| 127 | 127 |
| 128 | 128 |
| 129 Assignment::Assignment(Isolate* isolate, | 129 Assignment::Assignment(Zone* zone, |
| 130 Token::Value op, | 130 Token::Value op, |
| 131 Expression* target, | 131 Expression* target, |
| 132 Expression* value, | 132 Expression* value, |
| 133 int pos) | 133 int pos) |
| 134 : Expression(isolate, pos), | 134 : Expression(zone, pos), |
| 135 op_(op), | 135 op_(op), |
| 136 target_(target), | 136 target_(target), |
| 137 value_(value), | 137 value_(value), |
| 138 binary_operation_(NULL), | 138 binary_operation_(NULL), |
| 139 assignment_id_(GetNextId(isolate)), | 139 assignment_id_(GetNextId(zone)), |
| 140 is_uninitialized_(false), | 140 is_uninitialized_(false), |
| 141 is_pre_monomorphic_(false), | |
| 142 store_mode_(STANDARD_STORE) { } | 141 store_mode_(STANDARD_STORE) { } |
| 143 | 142 |
| 144 | 143 |
| 145 Token::Value Assignment::binary_op() const { | 144 Token::Value Assignment::binary_op() const { |
| 146 switch (op_) { | 145 switch (op_) { |
| 147 case Token::ASSIGN_BIT_OR: return Token::BIT_OR; | 146 case Token::ASSIGN_BIT_OR: return Token::BIT_OR; |
| 148 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; | 147 case Token::ASSIGN_BIT_XOR: return Token::BIT_XOR; |
| 149 case Token::ASSIGN_BIT_AND: return Token::BIT_AND; | 148 case Token::ASSIGN_BIT_AND: return Token::BIT_AND; |
| 150 case Token::ASSIGN_SHL: return Token::SHL; | 149 case Token::ASSIGN_SHL: return Token::SHL; |
| 151 case Token::ASSIGN_SAR: return Token::SAR; | 150 case Token::ASSIGN_SAR: return Token::SAR; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 195 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
| 197 if (shared->start_position() == start_position()) { | 196 if (shared->start_position() == start_position()) { |
| 198 shared_info_ = Handle<SharedFunctionInfo>(shared); | 197 shared_info_ = Handle<SharedFunctionInfo>(shared); |
| 199 break; | 198 break; |
| 200 } | 199 } |
| 201 } | 200 } |
| 202 } | 201 } |
| 203 } | 202 } |
| 204 | 203 |
| 205 | 204 |
| 206 ObjectLiteralProperty::ObjectLiteralProperty(Literal* key, | 205 ObjectLiteralProperty::ObjectLiteralProperty( |
| 207 Expression* value, | 206 Zone* zone, Literal* key, Expression* value) { |
| 208 Isolate* isolate) { | |
| 209 emit_store_ = true; | 207 emit_store_ = true; |
| 210 key_ = key; | 208 key_ = key; |
| 211 value_ = value; | 209 value_ = value; |
| 212 Object* k = *key->value(); | 210 Object* k = *key->value(); |
| 213 if (k->IsInternalizedString() && | 211 if (k->IsInternalizedString() && |
| 214 isolate->heap()->proto_string()->Equals(String::cast(k))) { | 212 zone->isolate()->heap()->proto_string()->Equals(String::cast(k))) { |
| 215 kind_ = PROTOTYPE; | 213 kind_ = PROTOTYPE; |
| 216 } else if (value_->AsMaterializedLiteral() != NULL) { | 214 } else if (value_->AsMaterializedLiteral() != NULL) { |
| 217 kind_ = MATERIALIZED_LITERAL; | 215 kind_ = MATERIALIZED_LITERAL; |
| 218 } else if (value_->AsLiteral() != NULL) { | 216 } else if (value_->AsLiteral() != NULL) { |
| 219 kind_ = CONSTANT; | 217 kind_ = CONSTANT; |
| 220 } else { | 218 } else { |
| 221 kind_ = COMPUTED; | 219 kind_ = COMPUTED; |
| 222 } | 220 } |
| 223 } | 221 } |
| 224 | 222 |
| 225 | 223 |
| 226 ObjectLiteralProperty::ObjectLiteralProperty(bool is_getter, | 224 ObjectLiteralProperty::ObjectLiteralProperty( |
| 227 FunctionLiteral* value) { | 225 Zone* zone, bool is_getter, FunctionLiteral* value) { |
| 228 emit_store_ = true; | 226 emit_store_ = true; |
| 229 value_ = value; | 227 value_ = value; |
| 230 kind_ = is_getter ? GETTER : SETTER; | 228 kind_ = is_getter ? GETTER : SETTER; |
| 231 } | 229 } |
| 232 | 230 |
| 233 | 231 |
| 234 bool ObjectLiteral::Property::IsCompileTimeValue() { | 232 bool ObjectLiteral::Property::IsCompileTimeValue() { |
| 235 return kind_ == CONSTANT || | 233 return kind_ == CONSTANT || |
| 236 (kind_ == MATERIALIZED_LITERAL && | 234 (kind_ == MATERIALIZED_LITERAL && |
| 237 CompileTimeValue::IsCompileTimeValue(value_)); | 235 CompileTimeValue::IsCompileTimeValue(value_)); |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 // Recording of type feedback | 586 // Recording of type feedback |
| 589 | 587 |
| 590 // TODO(rossberg): all RecordTypeFeedback functions should disappear | 588 // TODO(rossberg): all RecordTypeFeedback functions should disappear |
| 591 // once we use the common type field in the AST consistently. | 589 // once we use the common type field in the AST consistently. |
| 592 | 590 |
| 593 void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { | 591 void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) { |
| 594 to_boolean_types_ = oracle->ToBooleanTypes(test_id()); | 592 to_boolean_types_ = oracle->ToBooleanTypes(test_id()); |
| 595 } | 593 } |
| 596 | 594 |
| 597 | 595 |
| 596 int Call::ComputeFeedbackSlotCount(Isolate* isolate) { |
| 597 CallType call_type = GetCallType(isolate); |
| 598 if (call_type == LOOKUP_SLOT_CALL || call_type == OTHER_CALL) { |
| 599 // Call only uses a slot in some cases. |
| 600 return 1; |
| 601 } |
| 602 |
| 603 return 0; |
| 604 } |
| 605 |
| 606 |
| 598 Call::CallType Call::GetCallType(Isolate* isolate) const { | 607 Call::CallType Call::GetCallType(Isolate* isolate) const { |
| 599 VariableProxy* proxy = expression()->AsVariableProxy(); | 608 VariableProxy* proxy = expression()->AsVariableProxy(); |
| 600 if (proxy != NULL) { | 609 if (proxy != NULL) { |
| 601 if (proxy->var()->is_possibly_eval(isolate)) { | 610 if (proxy->var()->is_possibly_eval(isolate)) { |
| 602 return POSSIBLY_EVAL_CALL; | 611 return POSSIBLY_EVAL_CALL; |
| 603 } else if (proxy->var()->IsUnallocated()) { | 612 } else if (proxy->var()->IsUnallocated()) { |
| 604 return GLOBAL_CALL; | 613 return GLOBAL_CALL; |
| 605 } else if (proxy->var()->IsLookupSlot()) { | 614 } else if (proxy->var()->IsLookupSlot()) { |
| 606 return LOOKUP_SLOT_CALL; | 615 return LOOKUP_SLOT_CALL; |
| 607 } | 616 } |
| 608 } | 617 } |
| 609 | 618 |
| 610 Property* property = expression()->AsProperty(); | 619 Property* property = expression()->AsProperty(); |
| 611 return property != NULL ? PROPERTY_CALL : OTHER_CALL; | 620 return property != NULL ? PROPERTY_CALL : OTHER_CALL; |
| 612 } | 621 } |
| 613 | 622 |
| 614 | 623 |
| 615 bool Call::ComputeTarget(Handle<Map> type, Handle<String> name) { | |
| 616 // If there is an interceptor, we can't compute the target for a direct call. | |
| 617 if (type->has_named_interceptor()) return false; | |
| 618 | |
| 619 if (check_type_ == RECEIVER_MAP_CHECK) { | |
| 620 // For primitive checks the holder is set up to point to the corresponding | |
| 621 // prototype object, i.e. one step of the algorithm below has been already | |
| 622 // performed. For non-primitive checks we clear it to allow computing | |
| 623 // targets for polymorphic calls. | |
| 624 holder_ = Handle<JSObject>::null(); | |
| 625 } | |
| 626 LookupResult lookup(type->GetIsolate()); | |
| 627 while (true) { | |
| 628 // If a dictionary map is found in the prototype chain before the actual | |
| 629 // target, a new target can always appear. In that case, bail out. | |
| 630 // TODO(verwaest): Alternatively a runtime negative lookup on the normal | |
| 631 // receiver or prototype could be added. | |
| 632 if (type->is_dictionary_map()) return false; | |
| 633 type->LookupDescriptor(NULL, *name, &lookup); | |
| 634 if (lookup.IsFound()) { | |
| 635 switch (lookup.type()) { | |
| 636 case CONSTANT: { | |
| 637 // We surely know the target for a constant function. | |
| 638 Handle<Object> constant(lookup.GetConstantFromMap(*type), | |
| 639 type->GetIsolate()); | |
| 640 if (constant->IsJSFunction()) { | |
| 641 target_ = Handle<JSFunction>::cast(constant); | |
| 642 return true; | |
| 643 } | |
| 644 // Fall through. | |
| 645 } | |
| 646 case NORMAL: | |
| 647 case FIELD: | |
| 648 case CALLBACKS: | |
| 649 case HANDLER: | |
| 650 case INTERCEPTOR: | |
| 651 // We don't know the target. | |
| 652 return false; | |
| 653 case TRANSITION: | |
| 654 case NONEXISTENT: | |
| 655 UNREACHABLE(); | |
| 656 break; | |
| 657 } | |
| 658 } | |
| 659 // If we reach the end of the prototype chain, we don't know the target. | |
| 660 if (!type->prototype()->IsJSObject()) return false; | |
| 661 // Go up the prototype chain, recording where we are currently. | |
| 662 holder_ = Handle<JSObject>(JSObject::cast(type->prototype())); | |
| 663 type = Handle<Map>(holder()->map()); | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 | |
| 668 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global, | 624 bool Call::ComputeGlobalTarget(Handle<GlobalObject> global, |
| 669 LookupResult* lookup) { | 625 LookupResult* lookup) { |
| 670 target_ = Handle<JSFunction>::null(); | 626 target_ = Handle<JSFunction>::null(); |
| 671 cell_ = Handle<Cell>::null(); | 627 cell_ = Handle<Cell>::null(); |
| 672 ASSERT(lookup->IsFound() && | 628 ASSERT(lookup->IsFound() && |
| 673 lookup->type() == NORMAL && | 629 lookup->type() == NORMAL && |
| 674 lookup->holder() == *global); | 630 lookup->holder() == *global); |
| 675 cell_ = Handle<Cell>(global->GetPropertyCell(lookup)); | 631 cell_ = Handle<Cell>(global->GetPropertyCell(lookup)); |
| 676 if (cell_->value()->IsJSFunction()) { | 632 if (cell_->value()->IsJSFunction()) { |
| 677 Handle<JSFunction> candidate(JSFunction::cast(cell_->value())); | 633 Handle<JSFunction> candidate(JSFunction::cast(cell_->value())); |
| 678 // If the function is in new space we assume it's more likely to | 634 // If the function is in new space we assume it's more likely to |
| 679 // change and thus prefer the general IC code. | 635 // change and thus prefer the general IC code. |
| 680 if (!lookup->isolate()->heap()->InNewSpace(*candidate)) { | 636 if (!lookup->isolate()->heap()->InNewSpace(*candidate)) { |
| 681 target_ = candidate; | 637 target_ = candidate; |
| 682 return true; | 638 return true; |
| 683 } | 639 } |
| 684 } | 640 } |
| 685 return false; | 641 return false; |
| 686 } | 642 } |
| 687 | 643 |
| 688 | 644 |
| 689 Handle<JSObject> Call::GetPrototypeForPrimitiveCheck( | |
| 690 CheckType check, Isolate* isolate) { | |
| 691 v8::internal::Context* native_context = isolate->context()->native_context(); | |
| 692 JSFunction* function = NULL; | |
| 693 switch (check) { | |
| 694 case RECEIVER_MAP_CHECK: | |
| 695 UNREACHABLE(); | |
| 696 break; | |
| 697 case STRING_CHECK: | |
| 698 function = native_context->string_function(); | |
| 699 break; | |
| 700 case SYMBOL_CHECK: | |
| 701 function = native_context->symbol_function(); | |
| 702 break; | |
| 703 case NUMBER_CHECK: | |
| 704 function = native_context->number_function(); | |
| 705 break; | |
| 706 case BOOLEAN_CHECK: | |
| 707 function = native_context->boolean_function(); | |
| 708 break; | |
| 709 } | |
| 710 ASSERT(function != NULL); | |
| 711 return Handle<JSObject>(JSObject::cast(function->instance_prototype())); | |
| 712 } | |
| 713 | |
| 714 | |
| 715 void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | |
| 716 is_monomorphic_ = oracle->CallIsMonomorphic(CallFeedbackId()); | |
| 717 Property* property = expression()->AsProperty(); | |
| 718 if (property == NULL) { | |
| 719 // Function call. Specialize for monomorphic calls. | |
| 720 if (is_monomorphic_) target_ = oracle->GetCallTarget(CallFeedbackId()); | |
| 721 } else if (property->key()->IsPropertyName()) { | |
| 722 // Method call. Specialize for the receiver types seen at runtime. | |
| 723 Literal* key = property->key()->AsLiteral(); | |
| 724 ASSERT(key != NULL && key->value()->IsString()); | |
| 725 Handle<String> name = Handle<String>::cast(key->value()); | |
| 726 check_type_ = oracle->GetCallCheckType(CallFeedbackId()); | |
| 727 receiver_types_.Clear(); | |
| 728 if (check_type_ == RECEIVER_MAP_CHECK) { | |
| 729 oracle->CallReceiverTypes(CallFeedbackId(), | |
| 730 name, arguments()->length(), &receiver_types_); | |
| 731 is_monomorphic_ = is_monomorphic_ && receiver_types_.length() > 0; | |
| 732 } else { | |
| 733 holder_ = GetPrototypeForPrimitiveCheck(check_type_, oracle->isolate()); | |
| 734 receiver_types_.Add(handle(holder_->map()), oracle->zone()); | |
| 735 } | |
| 736 #ifdef ENABLE_SLOW_ASSERTS | |
| 737 if (FLAG_enable_slow_asserts) { | |
| 738 int length = receiver_types_.length(); | |
| 739 for (int i = 0; i < length; i++) { | |
| 740 Handle<Map> map = receiver_types_.at(i); | |
| 741 ASSERT(!map.is_null() && *map != NULL); | |
| 742 } | |
| 743 } | |
| 744 #endif | |
| 745 if (is_monomorphic_) { | |
| 746 Handle<Map> map = receiver_types_.first(); | |
| 747 is_monomorphic_ = ComputeTarget(map, name); | |
| 748 } | |
| 749 } else { | |
| 750 if (is_monomorphic_) { | |
| 751 keyed_array_call_is_holey_ = | |
| 752 oracle->KeyedArrayCallIsHoley(CallFeedbackId()); | |
| 753 } | |
| 754 } | |
| 755 } | |
| 756 | |
| 757 | |
| 758 void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 645 void CallNew::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 759 allocation_info_cell_ = | 646 allocation_site_ = |
| 760 oracle->GetCallNewAllocationInfoCell(CallNewFeedbackId()); | 647 oracle->GetCallNewAllocationSite(CallNewFeedbackSlot()); |
| 761 is_monomorphic_ = oracle->CallNewIsMonomorphic(CallNewFeedbackId()); | 648 is_monomorphic_ = oracle->CallNewIsMonomorphic(CallNewFeedbackSlot()); |
| 762 if (is_monomorphic_) { | 649 if (is_monomorphic_) { |
| 763 target_ = oracle->GetCallNewTarget(CallNewFeedbackId()); | 650 target_ = oracle->GetCallNewTarget(CallNewFeedbackSlot()); |
| 764 Object* value = allocation_info_cell_->value(); | 651 if (!allocation_site_.is_null()) { |
| 765 ASSERT(!value->IsTheHole()); | 652 elements_kind_ = allocation_site_->GetElementsKind(); |
| 766 if (value->IsAllocationSite()) { | |
| 767 AllocationSite* site = AllocationSite::cast(value); | |
| 768 elements_kind_ = site->GetElementsKind(); | |
| 769 } | 653 } |
| 770 } | 654 } |
| 771 } | 655 } |
| 772 | 656 |
| 773 | 657 |
| 774 void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { | 658 void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { |
| 775 TypeFeedbackId id = key()->LiteralFeedbackId(); | 659 TypeFeedbackId id = key()->LiteralFeedbackId(); |
| 776 SmallMapList maps; | 660 SmallMapList maps; |
| 777 oracle->CollectReceiverTypes(id, &maps); | 661 oracle->CollectReceiverTypes(id, &maps); |
| 778 receiver_type_ = maps.length() == 1 ? maps.at(0) | 662 receiver_type_ = maps.length() == 1 ? maps.at(0) |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1142 for (int i = 0; i < nodes->length(); i++) { | 1026 for (int i = 0; i < nodes->length(); i++) { |
| 1143 RegExpTree* node = nodes->at(i); | 1027 RegExpTree* node = nodes->at(i); |
| 1144 int node_min_match = node->min_match(); | 1028 int node_min_match = node->min_match(); |
| 1145 min_match_ = IncreaseBy(min_match_, node_min_match); | 1029 min_match_ = IncreaseBy(min_match_, node_min_match); |
| 1146 int node_max_match = node->max_match(); | 1030 int node_max_match = node->max_match(); |
| 1147 max_match_ = IncreaseBy(max_match_, node_max_match); | 1031 max_match_ = IncreaseBy(max_match_, node_max_match); |
| 1148 } | 1032 } |
| 1149 } | 1033 } |
| 1150 | 1034 |
| 1151 | 1035 |
| 1152 CaseClause::CaseClause(Isolate* isolate, | 1036 CaseClause::CaseClause(Zone* zone, |
| 1153 Expression* label, | 1037 Expression* label, |
| 1154 ZoneList<Statement*>* statements, | 1038 ZoneList<Statement*>* statements, |
| 1155 int pos) | 1039 int pos) |
| 1156 : Expression(isolate, pos), | 1040 : Expression(zone, pos), |
| 1157 label_(label), | 1041 label_(label), |
| 1158 statements_(statements), | 1042 statements_(statements), |
| 1159 compare_type_(Type::None(isolate)), | 1043 compare_type_(Type::None(zone)), |
| 1160 compare_id_(AstNode::GetNextId(isolate)), | 1044 compare_id_(AstNode::GetNextId(zone)), |
| 1161 entry_id_(AstNode::GetNextId(isolate)) { | 1045 entry_id_(AstNode::GetNextId(zone)) { |
| 1162 } | 1046 } |
| 1163 | 1047 |
| 1164 | 1048 |
| 1165 #define REGULAR_NODE(NodeType) \ | 1049 #define REGULAR_NODE(NodeType) \ |
| 1166 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ | 1050 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ |
| 1167 increase_node_count(); \ | 1051 increase_node_count(); \ |
| 1168 } | 1052 } |
| 1053 #define REGULAR_NODE_WITH_FEEDBACK_SLOTS(NodeType) \ |
| 1054 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ |
| 1055 increase_node_count(); \ |
| 1056 add_slot_node(node); \ |
| 1057 } |
| 1169 #define DONT_OPTIMIZE_NODE(NodeType) \ | 1058 #define DONT_OPTIMIZE_NODE(NodeType) \ |
| 1170 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ | 1059 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ |
| 1171 increase_node_count(); \ | 1060 increase_node_count(); \ |
| 1172 set_dont_optimize_reason(k##NodeType); \ | 1061 set_dont_optimize_reason(k##NodeType); \ |
| 1173 add_flag(kDontInline); \ | 1062 add_flag(kDontInline); \ |
| 1174 add_flag(kDontSelfOptimize); \ | 1063 add_flag(kDontSelfOptimize); \ |
| 1175 } | 1064 } |
| 1176 #define DONT_SELFOPTIMIZE_NODE(NodeType) \ | 1065 #define DONT_SELFOPTIMIZE_NODE(NodeType) \ |
| 1177 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ | 1066 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ |
| 1178 increase_node_count(); \ | 1067 increase_node_count(); \ |
| 1179 add_flag(kDontSelfOptimize); \ | 1068 add_flag(kDontSelfOptimize); \ |
| 1180 } | 1069 } |
| 1070 #define DONT_SELFOPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(NodeType) \ |
| 1071 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ |
| 1072 increase_node_count(); \ |
| 1073 add_slot_node(node); \ |
| 1074 add_flag(kDontSelfOptimize); \ |
| 1075 } |
| 1181 #define DONT_CACHE_NODE(NodeType) \ | 1076 #define DONT_CACHE_NODE(NodeType) \ |
| 1182 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ | 1077 void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \ |
| 1183 increase_node_count(); \ | 1078 increase_node_count(); \ |
| 1184 set_dont_optimize_reason(k##NodeType); \ | 1079 set_dont_optimize_reason(k##NodeType); \ |
| 1185 add_flag(kDontInline); \ | 1080 add_flag(kDontInline); \ |
| 1186 add_flag(kDontSelfOptimize); \ | 1081 add_flag(kDontSelfOptimize); \ |
| 1187 add_flag(kDontCache); \ | 1082 add_flag(kDontCache); \ |
| 1188 } | 1083 } |
| 1189 | 1084 |
| 1190 REGULAR_NODE(VariableDeclaration) | 1085 REGULAR_NODE(VariableDeclaration) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1205 REGULAR_NODE(RegExpLiteral) | 1100 REGULAR_NODE(RegExpLiteral) |
| 1206 REGULAR_NODE(FunctionLiteral) | 1101 REGULAR_NODE(FunctionLiteral) |
| 1207 REGULAR_NODE(Assignment) | 1102 REGULAR_NODE(Assignment) |
| 1208 REGULAR_NODE(Throw) | 1103 REGULAR_NODE(Throw) |
| 1209 REGULAR_NODE(Property) | 1104 REGULAR_NODE(Property) |
| 1210 REGULAR_NODE(UnaryOperation) | 1105 REGULAR_NODE(UnaryOperation) |
| 1211 REGULAR_NODE(CountOperation) | 1106 REGULAR_NODE(CountOperation) |
| 1212 REGULAR_NODE(BinaryOperation) | 1107 REGULAR_NODE(BinaryOperation) |
| 1213 REGULAR_NODE(CompareOperation) | 1108 REGULAR_NODE(CompareOperation) |
| 1214 REGULAR_NODE(ThisFunction) | 1109 REGULAR_NODE(ThisFunction) |
| 1215 REGULAR_NODE(Call) | 1110 REGULAR_NODE_WITH_FEEDBACK_SLOTS(Call) |
| 1216 REGULAR_NODE(CallNew) | 1111 REGULAR_NODE_WITH_FEEDBACK_SLOTS(CallNew) |
| 1217 // In theory, for VariableProxy we'd have to add: | 1112 // In theory, for VariableProxy we'd have to add: |
| 1218 // if (node->var()->IsLookupSlot()) add_flag(kDontInline); | 1113 // if (node->var()->IsLookupSlot()) add_flag(kDontInline); |
| 1219 // But node->var() is usually not bound yet at VariableProxy creation time, and | 1114 // But node->var() is usually not bound yet at VariableProxy creation time, and |
| 1220 // LOOKUP variables only result from constructs that cannot be inlined anyway. | 1115 // LOOKUP variables only result from constructs that cannot be inlined anyway. |
| 1221 REGULAR_NODE(VariableProxy) | 1116 REGULAR_NODE(VariableProxy) |
| 1222 | 1117 |
| 1223 // We currently do not optimize any modules. | 1118 // We currently do not optimize any modules. |
| 1224 DONT_OPTIMIZE_NODE(ModuleDeclaration) | 1119 DONT_OPTIMIZE_NODE(ModuleDeclaration) |
| 1225 DONT_OPTIMIZE_NODE(ImportDeclaration) | 1120 DONT_OPTIMIZE_NODE(ImportDeclaration) |
| 1226 DONT_OPTIMIZE_NODE(ExportDeclaration) | 1121 DONT_OPTIMIZE_NODE(ExportDeclaration) |
| 1227 DONT_OPTIMIZE_NODE(ModuleVariable) | 1122 DONT_OPTIMIZE_NODE(ModuleVariable) |
| 1228 DONT_OPTIMIZE_NODE(ModulePath) | 1123 DONT_OPTIMIZE_NODE(ModulePath) |
| 1229 DONT_OPTIMIZE_NODE(ModuleUrl) | 1124 DONT_OPTIMIZE_NODE(ModuleUrl) |
| 1230 DONT_OPTIMIZE_NODE(ModuleStatement) | 1125 DONT_OPTIMIZE_NODE(ModuleStatement) |
| 1231 DONT_OPTIMIZE_NODE(Yield) | 1126 DONT_OPTIMIZE_NODE(Yield) |
| 1232 DONT_OPTIMIZE_NODE(WithStatement) | 1127 DONT_OPTIMIZE_NODE(WithStatement) |
| 1233 DONT_OPTIMIZE_NODE(TryCatchStatement) | 1128 DONT_OPTIMIZE_NODE(TryCatchStatement) |
| 1234 DONT_OPTIMIZE_NODE(TryFinallyStatement) | 1129 DONT_OPTIMIZE_NODE(TryFinallyStatement) |
| 1235 DONT_OPTIMIZE_NODE(DebuggerStatement) | 1130 DONT_OPTIMIZE_NODE(DebuggerStatement) |
| 1236 DONT_OPTIMIZE_NODE(NativeFunctionLiteral) | 1131 DONT_OPTIMIZE_NODE(NativeFunctionLiteral) |
| 1237 | 1132 |
| 1238 DONT_SELFOPTIMIZE_NODE(DoWhileStatement) | 1133 DONT_SELFOPTIMIZE_NODE(DoWhileStatement) |
| 1239 DONT_SELFOPTIMIZE_NODE(WhileStatement) | 1134 DONT_SELFOPTIMIZE_NODE(WhileStatement) |
| 1240 DONT_SELFOPTIMIZE_NODE(ForStatement) | 1135 DONT_SELFOPTIMIZE_NODE(ForStatement) |
| 1241 DONT_SELFOPTIMIZE_NODE(ForInStatement) | 1136 DONT_SELFOPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(ForInStatement) |
| 1242 DONT_SELFOPTIMIZE_NODE(ForOfStatement) | 1137 DONT_SELFOPTIMIZE_NODE(ForOfStatement) |
| 1243 | 1138 |
| 1244 DONT_CACHE_NODE(ModuleLiteral) | 1139 DONT_CACHE_NODE(ModuleLiteral) |
| 1245 | 1140 |
| 1141 |
| 1246 void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { | 1142 void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { |
| 1247 increase_node_count(); | 1143 increase_node_count(); |
| 1248 if (node->is_jsruntime()) { | 1144 if (node->is_jsruntime()) { |
| 1249 // Don't try to inline JS runtime calls because we don't (currently) even | 1145 // Don't try to inline JS runtime calls because we don't (currently) even |
| 1250 // optimize them. | 1146 // optimize them. |
| 1251 add_flag(kDontInline); | 1147 add_flag(kDontInline); |
| 1252 } else if (node->function()->intrinsic_type == Runtime::INLINE && | 1148 } else if (node->function()->intrinsic_type == Runtime::INLINE && |
| 1253 (node->name()->IsOneByteEqualTo( | 1149 (node->name()->IsOneByteEqualTo( |
| 1254 STATIC_ASCII_VECTOR("_ArgumentsLength")) || | 1150 STATIC_ASCII_VECTOR("_ArgumentsLength")) || |
| 1255 node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) { | 1151 node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1277 OS::SNPrintF(buffer, "%d", Smi::cast(*value_)->value()); | 1173 OS::SNPrintF(buffer, "%d", Smi::cast(*value_)->value()); |
| 1278 str = arr; | 1174 str = arr; |
| 1279 } else { | 1175 } else { |
| 1280 str = DoubleToCString(value_->Number(), buffer); | 1176 str = DoubleToCString(value_->Number(), buffer); |
| 1281 } | 1177 } |
| 1282 return isolate_->factory()->NewStringFromAscii(CStrVector(str)); | 1178 return isolate_->factory()->NewStringFromAscii(CStrVector(str)); |
| 1283 } | 1179 } |
| 1284 | 1180 |
| 1285 | 1181 |
| 1286 } } // namespace v8::internal | 1182 } } // namespace v8::internal |
| OLD | NEW |