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

Side by Side Diff: src/hydrogen.cc

Issue 7824038: Remove variable rewrites and the unneccesary Slot class. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 3 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
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 3110 matching lines...) Expand 10 before | Expand all | Expand 10 after
3121 context = context_instruction; 3121 context = context_instruction;
3122 } 3122 }
3123 return context; 3123 return context;
3124 } 3124 }
3125 3125
3126 3126
3127 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 3127 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3128 ASSERT(!HasStackOverflow()); 3128 ASSERT(!HasStackOverflow());
3129 ASSERT(current_block() != NULL); 3129 ASSERT(current_block() != NULL);
3130 ASSERT(current_block()->HasPredecessor()); 3130 ASSERT(current_block()->HasPredecessor());
3131 Variable* variable = expr->AsVariable(); 3131 Variable* variable = expr->var();
3132 if (variable == NULL) { 3132 if (variable->mode() == Variable::LET) {
3133 return Bailout("reference to rewritten variable");
3134 } else if (variable->mode() == Variable::LET) {
3135 return Bailout("reference to let variable"); 3133 return Bailout("reference to let variable");
3136 } else if (variable->IsStackAllocated()) { 3134 }
3137 HValue* value = environment()->Lookup(variable); 3135 switch (variable->location()) {
3138 if (variable->mode() == Variable::CONST && 3136 case Variable::UNALLOCATED: {
3139 value == graph()->GetConstantHole()) { 3137 LookupResult lookup;
3140 return Bailout("reference to uninitialized const variable"); 3138 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false) ;
fschneider 2011/09/06 09:34:22 Long line.
3141 }
3142 return ast_context()->ReturnValue(value);
3143 } else if (variable->IsContextSlot()) {
3144 if (variable->mode() == Variable::CONST) {
3145 return Bailout("reference to const context slot");
3146 }
3147 HValue* context = BuildContextChainWalk(variable);
3148 int index = variable->AsSlot()->index();
3149 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index);
3150 return ast_context()->ReturnInstruction(instr, expr->id());
3151 } else if (variable->is_global()) {
3152 LookupResult lookup;
3153 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false);
3154 3139
3155 if (type == kUseCell && 3140 if (type == kUseCell &&
3156 info()->global_object()->IsAccessCheckNeeded()) { 3141 info()->global_object()->IsAccessCheckNeeded()) {
3157 type = kUseGeneric; 3142 type = kUseGeneric;
3143 }
3144
3145 if (type == kUseCell) {
3146 Handle<GlobalObject> global(info()->global_object());
3147 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3148 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3149 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
3150 return ast_context()->ReturnInstruction(instr, expr->id());
3151 } else {
3152 HValue* context = environment()->LookupContext();
3153 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3154 AddInstruction(global_object);
3155 HLoadGlobalGeneric* instr =
3156 new(zone()) HLoadGlobalGeneric(context,
3157 global_object,
3158 variable->name(),
3159 ast_context()->is_for_typeof());
3160 instr->set_position(expr->position());
3161 return ast_context()->ReturnInstruction(instr, expr->id());
3162 }
3158 } 3163 }
3159 3164
3160 if (type == kUseCell) { 3165 case Variable::PARAMETER:
3161 Handle<GlobalObject> global(info()->global_object()); 3166 case Variable::LOCAL: {
3162 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3167 HValue* value = environment()->Lookup(variable);
3163 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 3168 if (variable->mode() == Variable::CONST &&
3164 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); 3169 value == graph()->GetConstantHole()) {
3165 return ast_context()->ReturnInstruction(instr, expr->id()); 3170 return Bailout("reference to uninitialized const variable");
3166 } else { 3171 }
3167 HValue* context = environment()->LookupContext(); 3172 return ast_context()->ReturnValue(value);
3168 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3173 }
3169 AddInstruction(global_object); 3174
3170 HLoadGlobalGeneric* instr = 3175 case Variable::CONTEXT:{
3171 new(zone()) HLoadGlobalGeneric(context, 3176 if (variable->mode() == Variable::CONST) {
3172 global_object, 3177 return Bailout("reference to const context slot");
3173 variable->name(), 3178 }
3174 ast_context()->is_for_typeof()); 3179 HValue* context = BuildContextChainWalk(variable);
3175 instr->set_position(expr->position()); 3180 HLoadContextSlot* instr =
3176 ASSERT(instr->HasSideEffects()); 3181 new(zone()) HLoadContextSlot(context, variable->index());
3177 return ast_context()->ReturnInstruction(instr, expr->id()); 3182 return ast_context()->ReturnInstruction(instr, expr->id());
3178 } 3183 }
3179 } else { 3184
3180 return Bailout("reference to a variable which requires dynamic lookup"); 3185 case Variable::LOOKUP:
3186 return Bailout("reference to a variable which requires dynamic lookup");
3181 } 3187 }
3182 } 3188 }
3183 3189
3184 3190
3185 void HGraphBuilder::VisitLiteral(Literal* expr) { 3191 void HGraphBuilder::VisitLiteral(Literal* expr) {
3186 ASSERT(!HasStackOverflow()); 3192 ASSERT(!HasStackOverflow());
3187 ASSERT(current_block() != NULL); 3193 ASSERT(current_block() != NULL);
3188 ASSERT(current_block()->HasPredecessor()); 3194 ASSERT(current_block()->HasPredecessor());
3189 HConstant* instr = 3195 HConstant* instr =
3190 new(zone()) HConstant(expr->handle(), Representation::Tagged()); 3196 new(zone()) HConstant(expr->handle(), Representation::Tagged());
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
3582 AddInstruction(instr); 3588 AddInstruction(instr);
3583 ASSERT(instr->HasSideEffects()); 3589 ASSERT(instr->HasSideEffects());
3584 if (instr->HasSideEffects()) AddSimulate(ast_id); 3590 if (instr->HasSideEffects()) AddSimulate(ast_id);
3585 } 3591 }
3586 } 3592 }
3587 3593
3588 3594
3589 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3595 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3590 Expression* target = expr->target(); 3596 Expression* target = expr->target();
3591 VariableProxy* proxy = target->AsVariableProxy(); 3597 VariableProxy* proxy = target->AsVariableProxy();
3592 Variable* var = proxy->AsVariable();
3593 Property* prop = target->AsProperty(); 3598 Property* prop = target->AsProperty();
3594 ASSERT(var == NULL || prop == NULL); 3599 ASSERT(proxy == NULL || prop == NULL);
3595 3600
3596 // We have a second position recorded in the FullCodeGenerator to have 3601 // We have a second position recorded in the FullCodeGenerator to have
3597 // type feedback for the binary operation. 3602 // type feedback for the binary operation.
3598 BinaryOperation* operation = expr->binary_operation(); 3603 BinaryOperation* operation = expr->binary_operation();
3599 3604
3600 if (var != NULL) { 3605 if (proxy != NULL) {
3601 if (var->mode() == Variable::CONST || 3606 Variable* var = proxy->var();
3602 var->mode() == Variable::LET) { 3607 if (var->mode() == Variable::CONST || var->mode() == Variable::LET) {
3603 return Bailout("unsupported let or const compound assignment"); 3608 return Bailout("unsupported let or const compound assignment");
3604 } 3609 }
3605 3610
3606 CHECK_ALIVE(VisitForValue(operation)); 3611 CHECK_ALIVE(VisitForValue(operation));
3607 3612
3608 if (var->is_global()) { 3613 switch (var->location()) {
3609 HandleGlobalVariableAssignment(var, 3614 case Variable::UNALLOCATED:
3610 Top(), 3615 HandleGlobalVariableAssignment(var,
3611 expr->position(), 3616 Top(),
3612 expr->AssignmentId()); 3617 expr->position(),
3613 } else if (var->IsStackAllocated()) { 3618 expr->AssignmentId());
3614 Bind(var, Top()); 3619 break;
3615 } else if (var->IsContextSlot()) { 3620
3616 // Bail out if we try to mutate a parameter value in a function using 3621 case Variable::PARAMETER:
3617 // the arguments object. We do not (yet) correctly handle the 3622 case Variable::LOCAL:
3618 // arguments property of the function. 3623 Bind(var, Top());
3619 if (info()->scope()->arguments() != NULL) { 3624 break;
3620 // Parameters will rewrite to context slots. We have no direct way 3625
3621 // to detect that the variable is a parameter. 3626 case Variable::CONTEXT: {
3622 int count = info()->scope()->num_parameters(); 3627 // Bail out if we try to mutate a parameter value in a function
3623 for (int i = 0; i < count; ++i) { 3628 // using the arguments object. We do not (yet) correctly handle the
3624 if (var == info()->scope()->parameter(i)) { 3629 // arguments property of the function.
3625 Bailout("assignment to parameter, function uses arguments object"); 3630 if (info()->scope()->arguments() != NULL) {
3631 // Parameters will be allocated to context slots. We have no
3632 // direct way to detect that the variable is a parameter so we do
3633 // a linear search of the parameter variables.
3634 int count = info()->scope()->num_parameters();
3635 for (int i = 0; i < count; ++i) {
3636 if (var == info()->scope()->parameter(i)) {
3637 Bailout("assignment to parameter, function uses arguments object") ;
fschneider 2011/09/06 09:34:22 Long line.
3638 }
3626 } 3639 }
3627 } 3640 }
3641
3642 HValue* context = BuildContextChainWalk(var);
3643 HStoreContextSlot* instr =
3644 new(zone()) HStoreContextSlot(context, var->index(), Top());
3645 AddInstruction(instr);
3646 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3647 break;
3628 } 3648 }
3629 3649
3630 HValue* context = BuildContextChainWalk(var); 3650 case Variable::LOOKUP:
3631 int index = var->AsSlot()->index(); 3651 return Bailout("compound assignment to lookup slot");
3632 HStoreContextSlot* instr =
3633 new(zone()) HStoreContextSlot(context, index, Top());
3634 AddInstruction(instr);
3635 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3636 } else {
3637 return Bailout("compound assignment to lookup slot");
3638 } 3652 }
3639 return ast_context()->ReturnValue(Pop()); 3653 return ast_context()->ReturnValue(Pop());
3640 3654
3641 } else if (prop != NULL) { 3655 } else if (prop != NULL) {
3642 prop->RecordTypeFeedback(oracle()); 3656 prop->RecordTypeFeedback(oracle());
3643 3657
3644 if (prop->key()->IsPropertyName()) { 3658 if (prop->key()->IsPropertyName()) {
3645 // Named property. 3659 // Named property.
3646 CHECK_ALIVE(VisitForValue(prop->obj())); 3660 CHECK_ALIVE(VisitForValue(prop->obj()));
3647 HValue* obj = Top(); 3661 HValue* obj = Top();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3715 return Bailout("invalid lhs in compound assignment"); 3729 return Bailout("invalid lhs in compound assignment");
3716 } 3730 }
3717 } 3731 }
3718 3732
3719 3733
3720 void HGraphBuilder::VisitAssignment(Assignment* expr) { 3734 void HGraphBuilder::VisitAssignment(Assignment* expr) {
3721 ASSERT(!HasStackOverflow()); 3735 ASSERT(!HasStackOverflow());
3722 ASSERT(current_block() != NULL); 3736 ASSERT(current_block() != NULL);
3723 ASSERT(current_block()->HasPredecessor()); 3737 ASSERT(current_block()->HasPredecessor());
3724 VariableProxy* proxy = expr->target()->AsVariableProxy(); 3738 VariableProxy* proxy = expr->target()->AsVariableProxy();
3725 Variable* var = proxy->AsVariable();
3726 Property* prop = expr->target()->AsProperty(); 3739 Property* prop = expr->target()->AsProperty();
3727 ASSERT(var == NULL || prop == NULL); 3740 ASSERT(proxy == NULL || prop == NULL);
3728 3741
3729 if (expr->is_compound()) { 3742 if (expr->is_compound()) {
3730 HandleCompoundAssignment(expr); 3743 HandleCompoundAssignment(expr);
3731 return; 3744 return;
3732 } 3745 }
3733 3746
3734 if (var != NULL) { 3747 if (prop != NULL) {
3748 HandlePropertyAssignment(expr);
3749 } else if (proxy != NULL) {
3750 Variable* var = proxy->var();
3735 if (var->mode() == Variable::CONST) { 3751 if (var->mode() == Variable::CONST) {
3736 if (expr->op() != Token::INIT_CONST) { 3752 if (expr->op() != Token::INIT_CONST) {
3737 return Bailout("non-initializer assignment to const"); 3753 return Bailout("non-initializer assignment to const");
3738 } 3754 }
3739 if (!var->IsStackAllocated()) { 3755 if (!var->IsStackAllocated()) {
3740 return Bailout("assignment to const context slot"); 3756 return Bailout("assignment to const context slot");
3741 } 3757 }
3742 // We insert a use of the old value to detect unsupported uses of const 3758 // We insert a use of the old value to detect unsupported uses of const
3743 // variables (e.g. initialization inside a loop). 3759 // variables (e.g. initialization inside a loop).
3744 HValue* old_value = environment()->Lookup(var); 3760 HValue* old_value = environment()->Lookup(var);
3745 AddInstruction(new HUseConst(old_value)); 3761 AddInstruction(new HUseConst(old_value));
3746 } else if (var->mode() == Variable::LET) { 3762 } else if (var->mode() == Variable::LET) {
3747 return Bailout("unsupported assignment to let"); 3763 return Bailout("unsupported assignment to let");
3748 } 3764 }
3749 3765
3750 if (proxy->IsArguments()) return Bailout("assignment to arguments"); 3766 if (proxy->IsArguments()) return Bailout("assignment to arguments");
3751 3767
3752 // Handle the assignment. 3768 // Handle the assignment.
3753 if (var->IsStackAllocated()) { 3769 switch (var->location()) {
3754 // We do not allow the arguments object to occur in a context where it 3770 case Variable::UNALLOCATED:
3755 // may escape, but assignments to stack-allocated locals are 3771 CHECK_ALIVE(VisitForValue(expr->value()));
3756 // permitted. 3772 HandleGlobalVariableAssignment(var,
3757 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); 3773 Top(),
3758 HValue* value = Pop(); 3774 expr->position(),
3759 Bind(var, value); 3775 expr->AssignmentId());
3760 return ast_context()->ReturnValue(value); 3776 return ast_context()->ReturnValue(Pop());
3761 3777
3762 } else if (var->IsContextSlot()) { 3778 case Variable::PARAMETER:
3763 ASSERT(var->mode() != Variable::CONST); 3779 case Variable::LOCAL: {
3764 // Bail out if we try to mutate a parameter value in a function using 3780 // We do not allow the arguments object to occur in a context where it
3765 // the arguments object. We do not (yet) correctly handle the 3781 // may escape, but assignments to stack-allocated locals are
3766 // arguments property of the function. 3782 // permitted.
3767 if (info()->scope()->arguments() != NULL) { 3783 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
3768 // Parameters will rewrite to context slots. We have no direct way 3784 HValue* value = Pop();
3769 // to detect that the variable is a parameter. 3785 Bind(var, value);
3770 int count = info()->scope()->num_parameters(); 3786 return ast_context()->ReturnValue(value);
3771 for (int i = 0; i < count; ++i) { 3787 }
3772 if (var == info()->scope()->parameter(i)) { 3788
3773 Bailout("assignment to parameter, function uses arguments object"); 3789 case Variable::CONTEXT: {
3790 ASSERT(var->mode() != Variable::CONST);
3791 // Bail out if we try to mutate a parameter value in a function using
3792 // the arguments object. We do not (yet) correctly handle the
3793 // arguments property of the function.
3794 if (info()->scope()->arguments() != NULL) {
3795 // Parameters will rewrite to context slots. We have no direct way
3796 // to detect that the variable is a parameter.
3797 int count = info()->scope()->num_parameters();
3798 for (int i = 0; i < count; ++i) {
3799 if (var == info()->scope()->parameter(i)) {
3800 return Bailout("assignment to parameter in arguments object");
3801 }
3774 } 3802 }
3775 } 3803 }
3804
3805 CHECK_ALIVE(VisitForValue(expr->value()));
3806 HValue* context = BuildContextChainWalk(var);
3807 HStoreContextSlot* instr =
3808 new(zone()) HStoreContextSlot(context, var->index(), Top());
3809 AddInstruction(instr);
3810 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3811 return ast_context()->ReturnValue(Pop());
3776 } 3812 }
3777 3813
3778 CHECK_ALIVE(VisitForValue(expr->value())); 3814 case Variable::LOOKUP:
3779 HValue* context = BuildContextChainWalk(var); 3815 return Bailout("assignment to LOOKUP variable");
3780 int index = var->AsSlot()->index();
3781 HStoreContextSlot* instr =
3782 new(zone()) HStoreContextSlot(context, index, Top());
3783 AddInstruction(instr);
3784 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3785 return ast_context()->ReturnValue(Pop());
3786
3787 } else if (var->is_global()) {
3788 CHECK_ALIVE(VisitForValue(expr->value()));
3789 HandleGlobalVariableAssignment(var,
3790 Top(),
3791 expr->position(),
3792 expr->AssignmentId());
3793 return ast_context()->ReturnValue(Pop());
3794
3795 } else {
3796 return Bailout("assignment to LOOKUP or const CONTEXT variable");
3797 } 3816 }
3798
3799 } else if (prop != NULL) {
3800 HandlePropertyAssignment(expr);
3801 } else { 3817 } else {
3802 return Bailout("invalid left-hand side in assignment"); 3818 return Bailout("invalid left-hand side in assignment");
3803 } 3819 }
3804 } 3820 }
3805 3821
3806 3822
3807 void HGraphBuilder::VisitThrow(Throw* expr) { 3823 void HGraphBuilder::VisitThrow(Throw* expr) {
3808 ASSERT(!HasStackOverflow()); 3824 ASSERT(!HasStackOverflow());
3809 ASSERT(current_block() != NULL); 3825 ASSERT(current_block() != NULL);
3810 ASSERT(current_block()->HasPredecessor()); 3826 ASSERT(current_block()->HasPredecessor());
(...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after
4902 HandlePolymorphicCallNamed(expr, receiver, types, name); 4918 HandlePolymorphicCallNamed(expr, receiver, types, name);
4903 return; 4919 return;
4904 4920
4905 } else { 4921 } else {
4906 HValue* context = environment()->LookupContext(); 4922 HValue* context = environment()->LookupContext();
4907 call = PreProcessCall( 4923 call = PreProcessCall(
4908 new(zone()) HCallNamed(context, name, argument_count)); 4924 new(zone()) HCallNamed(context, name, argument_count));
4909 } 4925 }
4910 4926
4911 } else { 4927 } else {
4912 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4928 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4913 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4929 // FIXME.
fschneider 2011/09/06 09:34:22 Is this a TODO?
Kevin Millikin (Chromium) 2011/09/06 10:44:06 Oops. It was a TODO, but it's been fixed and I di
4930 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
4914 4931
4915 if (global_call) { 4932 if (global_call) {
4933 Variable* var = proxy->var();
4916 bool known_global_function = false; 4934 bool known_global_function = false;
4917 // If there is a global property cell for the name at compile time and 4935 // If there is a global property cell for the name at compile time and
4918 // access check is not enabled we assume that the function will not change 4936 // access check is not enabled we assume that the function will not change
4919 // and generate optimized code for calling the function. 4937 // and generate optimized code for calling the function.
4920 LookupResult lookup; 4938 LookupResult lookup;
4921 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 4939 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
4922 if (type == kUseCell && 4940 if (type == kUseCell &&
4923 !info()->global_object()->IsAccessCheckNeeded()) { 4941 !info()->global_object()->IsAccessCheckNeeded()) {
4924 Handle<GlobalObject> global(info()->global_object()); 4942 Handle<GlobalObject> global(info()->global_object());
4925 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 4943 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
5069 case Token::ADD: return VisitAdd(expr); 5087 case Token::ADD: return VisitAdd(expr);
5070 case Token::SUB: return VisitSub(expr); 5088 case Token::SUB: return VisitSub(expr);
5071 case Token::BIT_NOT: return VisitBitNot(expr); 5089 case Token::BIT_NOT: return VisitBitNot(expr);
5072 case Token::NOT: return VisitNot(expr); 5090 case Token::NOT: return VisitNot(expr);
5073 default: UNREACHABLE(); 5091 default: UNREACHABLE();
5074 } 5092 }
5075 } 5093 }
5076 5094
5077 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { 5095 void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
5078 Property* prop = expr->expression()->AsProperty(); 5096 Property* prop = expr->expression()->AsProperty();
5079 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 5097 VariableProxy* proxy = expr->expression()->AsVariableProxy();
5080 if (prop == NULL && var == NULL) { 5098 if (prop != NULL) {
5081 // Result of deleting non-property, non-variable reference is true.
5082 // Evaluate the subexpression for side effects.
5083 CHECK_ALIVE(VisitForEffect(expr->expression()));
5084 return ast_context()->ReturnValue(graph()->GetConstantTrue());
5085 } else if (var != NULL &&
5086 !var->is_global() &&
5087 var->AsSlot() != NULL &&
5088 var->AsSlot()->type() != Slot::LOOKUP) {
5089 // Result of deleting non-global, non-dynamic variables is false.
5090 // The subexpression does not have side effects.
5091 return ast_context()->ReturnValue(graph()->GetConstantFalse());
5092 } else if (prop != NULL) {
5093 CHECK_ALIVE(VisitForValue(prop->obj())); 5099 CHECK_ALIVE(VisitForValue(prop->obj()));
5094 CHECK_ALIVE(VisitForValue(prop->key())); 5100 CHECK_ALIVE(VisitForValue(prop->key()));
5095 HValue* key = Pop(); 5101 HValue* key = Pop();
5096 HValue* obj = Pop(); 5102 HValue* obj = Pop();
5097 HValue* context = environment()->LookupContext(); 5103 HValue* context = environment()->LookupContext();
5098 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); 5104 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
5099 return ast_context()->ReturnInstruction(instr, expr->id()); 5105 return ast_context()->ReturnInstruction(instr, expr->id());
5100 } else if (var->is_global()) { 5106 } else if (proxy != NULL) {
5101 Bailout("delete with global variable"); 5107 Variable* var = proxy->var();
5108 if (var->IsUnallocated()) {
5109 Bailout("delete with global variable");
5110 } else if (var->IsStackAllocated() || var->IsContextSlot()) {
5111 // Result of deleting non-global variables is false. 'this' is not
5112 // really a variable, though we implement it as one. The
5113 // subexpression does not have side effects.
5114 HValue* value = var->is_this()
5115 ? graph()->GetConstantTrue()
5116 : graph()->GetConstantFalse();
5117 return ast_context()->ReturnValue(value);
5118 } else {
5119 Bailout("delete with non-global variable");
5120 }
5102 } else { 5121 } else {
5103 Bailout("delete with non-global variable"); 5122 // Result of deleting non-property, non-variable reference is true.
5123 // Evaluate the subexpression for side effects.
5124 CHECK_ALIVE(VisitForEffect(expr->expression()));
5125 return ast_context()->ReturnValue(graph()->GetConstantTrue());
5104 } 5126 }
5105 } 5127 }
5106 5128
5107 5129
5108 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { 5130 void HGraphBuilder::VisitVoid(UnaryOperation* expr) {
5109 CHECK_ALIVE(VisitForEffect(expr->expression())); 5131 CHECK_ALIVE(VisitForEffect(expr->expression()));
5110 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 5132 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
5111 } 5133 }
5112 5134
5113 5135
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
5240 return instr; 5262 return instr;
5241 } 5263 }
5242 5264
5243 5265
5244 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { 5266 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
5245 ASSERT(!HasStackOverflow()); 5267 ASSERT(!HasStackOverflow());
5246 ASSERT(current_block() != NULL); 5268 ASSERT(current_block() != NULL);
5247 ASSERT(current_block()->HasPredecessor()); 5269 ASSERT(current_block()->HasPredecessor());
5248 Expression* target = expr->expression(); 5270 Expression* target = expr->expression();
5249 VariableProxy* proxy = target->AsVariableProxy(); 5271 VariableProxy* proxy = target->AsVariableProxy();
5250 Variable* var = proxy->AsVariable();
5251 Property* prop = target->AsProperty(); 5272 Property* prop = target->AsProperty();
5252 if (var == NULL && prop == NULL) { 5273 if (proxy == NULL && prop == NULL) {
5253 return Bailout("invalid lhs in count operation"); 5274 return Bailout("invalid lhs in count operation");
5254 } 5275 }
5255 5276
5256 // Match the full code generator stack by simulating an extra stack 5277 // Match the full code generator stack by simulating an extra stack
5257 // element for postfix operations in a non-effect context. The return 5278 // element for postfix operations in a non-effect context. The return
5258 // value is ToNumber(input). 5279 // value is ToNumber(input).
5259 bool returns_original_input = 5280 bool returns_original_input =
5260 expr->is_postfix() && !ast_context()->IsEffect(); 5281 expr->is_postfix() && !ast_context()->IsEffect();
5261 HValue* input = NULL; // ToNumber(original_input). 5282 HValue* input = NULL; // ToNumber(original_input).
5262 HValue* after = NULL; // The result after incrementing or decrementing. 5283 HValue* after = NULL; // The result after incrementing or decrementing.
5263 5284
5264 if (var != NULL) { 5285 if (proxy != NULL) {
5286 Variable* var = proxy->var();
5265 if (var->mode() == Variable::CONST) { 5287 if (var->mode() == Variable::CONST) {
5266 return Bailout("unsupported count operation with const"); 5288 return Bailout("unsupported count operation with const");
5267 } 5289 }
5268 // Argument of the count operation is a variable, not a property. 5290 // Argument of the count operation is a variable, not a property.
5269 ASSERT(prop == NULL); 5291 ASSERT(prop == NULL);
5270 CHECK_ALIVE(VisitForValue(target)); 5292 CHECK_ALIVE(VisitForValue(target));
5271 5293
5272 after = BuildIncrement(returns_original_input, expr); 5294 after = BuildIncrement(returns_original_input, expr);
5273 input = returns_original_input ? Top() : Pop(); 5295 input = returns_original_input ? Top() : Pop();
5274 Push(after); 5296 Push(after);
5275 5297
5276 if (var->is_global()) { 5298 switch (var->location()) {
5277 HandleGlobalVariableAssignment(var, 5299 case Variable::UNALLOCATED:
5278 after, 5300 HandleGlobalVariableAssignment(var,
5279 expr->position(), 5301 after,
5280 expr->AssignmentId()); 5302 expr->position(),
5281 } else if (var->IsStackAllocated()) { 5303 expr->AssignmentId());
5282 Bind(var, after); 5304 break;
5283 } else if (var->IsContextSlot()) { 5305
5284 // Bail out if we try to mutate a parameter value in a function using 5306 case Variable::PARAMETER:
5285 // the arguments object. We do not (yet) correctly handle the 5307 case Variable::LOCAL:
5286 // arguments property of the function. 5308 Bind(var, after);
5287 if (info()->scope()->arguments() != NULL) { 5309 break;
5288 // Parameters will rewrite to context slots. We have no direct way 5310
5289 // to detect that the variable is a parameter. 5311 case Variable::CONTEXT: {
5290 int count = info()->scope()->num_parameters(); 5312 // Bail out if we try to mutate a parameter value in a function
5291 for (int i = 0; i < count; ++i) { 5313 // using the arguments object. We do not (yet) correctly handle the
5292 if (var == info()->scope()->parameter(i)) { 5314 // arguments property of the function.
5293 Bailout("assignment to parameter, function uses arguments object"); 5315 if (info()->scope()->arguments() != NULL) {
5316 // Parameters will rewrite to context slots. We have no direct
5317 // way to detect that the variable is a parameter so we use a
5318 // linear search of the parameter list.
5319 int count = info()->scope()->num_parameters();
5320 for (int i = 0; i < count; ++i) {
5321 if (var == info()->scope()->parameter(i)) {
5322 return Bailout("assignment to parameter in arguments object");
5323 }
5294 } 5324 }
5295 } 5325 }
5326
5327 HValue* context = BuildContextChainWalk(var);
5328 HStoreContextSlot* instr =
5329 new(zone()) HStoreContextSlot(context, var->index(), after);
5330 AddInstruction(instr);
5331 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
5332 break;
5296 } 5333 }
5297 5334
5298 HValue* context = BuildContextChainWalk(var); 5335 case Variable::LOOKUP:
5299 int index = var->AsSlot()->index(); 5336 return Bailout("lookup variable in count operation");
5300 HStoreContextSlot* instr =
5301 new(zone()) HStoreContextSlot(context, index, after);
5302 AddInstruction(instr);
5303 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
5304 } else {
5305 return Bailout("lookup variable in count operation");
5306 } 5337 }
5307 5338
5308 } else { 5339 } else {
5309 // Argument of the count operation is a property. 5340 // Argument of the count operation is a property.
5310 ASSERT(prop != NULL); 5341 ASSERT(prop != NULL);
5311 prop->RecordTypeFeedback(oracle()); 5342 prop->RecordTypeFeedback(oracle());
5312 5343
5313 if (prop->key()->IsPropertyName()) { 5344 if (prop->key()->IsPropertyName()) {
5314 // Named property. 5345 // Named property.
5315 if (returns_original_input) Push(graph_->GetConstantUndefined()); 5346 if (returns_original_input) Push(graph_->GetConstantUndefined());
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
5707 HValue* context = environment()->LookupContext(); 5738 HValue* context = environment()->LookupContext();
5708 HValue* right = Pop(); 5739 HValue* right = Pop();
5709 HValue* left = Pop(); 5740 HValue* left = Pop();
5710 Token::Value op = expr->op(); 5741 Token::Value op = expr->op();
5711 5742
5712 if (op == Token::INSTANCEOF) { 5743 if (op == Token::INSTANCEOF) {
5713 // Check to see if the rhs of the instanceof is a global function not 5744 // Check to see if the rhs of the instanceof is a global function not
5714 // residing in new space. If it is we assume that the function will stay the 5745 // residing in new space. If it is we assume that the function will stay the
5715 // same. 5746 // same.
5716 Handle<JSFunction> target = Handle<JSFunction>::null(); 5747 Handle<JSFunction> target = Handle<JSFunction>::null();
5717 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 5748 VariableProxy* proxy = expr->right()->AsVariableProxy();
5718 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 5749 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
5719 if (global_function && 5750 if (global_function &&
5720 info()->has_global_object() && 5751 info()->has_global_object() &&
5721 !info()->global_object()->IsAccessCheckNeeded()) { 5752 !info()->global_object()->IsAccessCheckNeeded()) {
5722 Handle<String> name = var->name(); 5753 Handle<String> name = proxy->name();
5723 Handle<GlobalObject> global(info()->global_object()); 5754 Handle<GlobalObject> global(info()->global_object());
5724 LookupResult lookup; 5755 LookupResult lookup;
5725 global->Lookup(*name, &lookup); 5756 global->Lookup(*name, &lookup);
5726 if (lookup.IsProperty() && 5757 if (lookup.IsProperty() &&
5727 lookup.type() == NORMAL && 5758 lookup.type() == NORMAL &&
5728 lookup.GetValue()->IsJSFunction()) { 5759 lookup.GetValue()->IsJSFunction()) {
5729 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 5760 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5730 // If the function is in new space we assume it's more likely to 5761 // If the function is in new space we assume it's more likely to
5731 // change and thus prefer the general IC code. 5762 // change and thus prefer the general IC code.
5732 if (!isolate()->heap()->InNewSpace(*candidate)) { 5763 if (!isolate()->heap()->InNewSpace(*candidate)) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
5816 return ast_context()->ReturnInstruction(self, expr->id()); 5847 return ast_context()->ReturnInstruction(self, expr->id());
5817 } 5848 }
5818 5849
5819 5850
5820 void HGraphBuilder::VisitDeclaration(Declaration* decl) { 5851 void HGraphBuilder::VisitDeclaration(Declaration* decl) {
5821 HandleDeclaration(decl->proxy(), decl->mode(), decl->fun()); 5852 HandleDeclaration(decl->proxy(), decl->mode(), decl->fun());
5822 } 5853 }
5823 5854
5824 5855
5825 void HGraphBuilder::HandleDeclaration(VariableProxy* proxy, 5856 void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
5826 Variable::Mode mode, 5857 Variable::Mode mode,
5827 FunctionLiteral* function) { 5858 FunctionLiteral* function) {
5828 if (mode == Variable::LET) return Bailout("unsupported let declaration"); 5859 if (mode == Variable::LET) return Bailout("unsupported let declaration");
5829 Variable* var = proxy->var(); 5860 Variable* var = proxy->var();
5830 Slot* slot = var->AsSlot(); 5861 switch (var->location()) {
5831 ASSERT(slot != NULL); 5862 case Variable::UNALLOCATED:
5832 switch (slot->type()) { 5863 return Bailout("unsupported global declaration");
5833 case Slot::PARAMETER: 5864 case Variable::PARAMETER:
5834 case Slot::LOCAL: 5865 case Variable::LOCAL:
5835 if (mode == Variable::CONST) { 5866 case Variable::CONTEXT:
5836 environment()->Bind(var, graph()->GetConstantHole()); 5867 if (mode == Variable::CONST || function != NULL) {
5837 } else if (function != NULL) { 5868 HValue* value = NULL;
5838 VisitForValue(function); 5869 if (mode == Variable::CONST) {
5839 HValue* function_value = Pop(); 5870 value = graph()->GetConstantHole();
5840 environment()->Bind(var, function_value); 5871 } else {
5872 VisitForValue(function);
5873 value = Pop();
5874 }
5875 if (var->IsContextSlot()) {
5876 HValue* context = environment()->LookupContext();
5877 HStoreContextSlot* store =
5878 new HStoreContextSlot(context, var->index(), value);
5879 AddInstruction(store);
5880 if (store->HasSideEffects()) AddSimulate(proxy->id());
5881 } else {
5882 environment()->Bind(var, value);
5883 }
5841 } 5884 }
5842 break; 5885 break;
5843 case Slot::CONTEXT: { 5886 case Variable::LOOKUP:
5844 HValue* context = environment()->LookupContext();
5845 if (mode == Variable::CONST) {
5846 HStoreContextSlot* store =
5847 new HStoreContextSlot(context,
5848 slot->index(),
5849 graph()->GetConstantHole());
5850 AddInstruction(store);
5851 if (store->HasSideEffects()) AddSimulate(proxy->id());
5852 } else if (function != NULL) {
5853 VisitForValue(function);
5854 HValue* function_value = Pop();
5855 HStoreContextSlot* store =
5856 new HStoreContextSlot(context,
5857 slot->index(),
5858 function_value);
5859 AddInstruction(store);
5860 if (store->HasSideEffects()) AddSimulate(proxy->id());
5861 }
5862 break;
5863 }
5864 case Slot::LOOKUP:
5865 return Bailout("unsupported lookup slot in declaration"); 5887 return Bailout("unsupported lookup slot in declaration");
5866 } 5888 }
5867 } 5889 }
5868 5890
5869 5891
5870 // Generators for inline runtime functions. 5892 // Generators for inline runtime functions.
5871 // Support for types. 5893 // Support for types.
5872 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { 5894 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
5873 ASSERT(call->arguments()->length() == 1); 5895 ASSERT(call->arguments()->length() == 1);
5874 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5896 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after
6792 } 6814 }
6793 } 6815 }
6794 6816
6795 #ifdef DEBUG 6817 #ifdef DEBUG
6796 if (graph_ != NULL) graph_->Verify(); 6818 if (graph_ != NULL) graph_->Verify();
6797 if (allocator_ != NULL) allocator_->Verify(); 6819 if (allocator_ != NULL) allocator_->Verify();
6798 #endif 6820 #endif
6799 } 6821 }
6800 6822
6801 } } // namespace v8::internal 6823 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698