OLD | NEW |
---|---|
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 1943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1954 | 1954 |
1955 FunctionState::~FunctionState() { | 1955 FunctionState::~FunctionState() { |
1956 delete test_context_; | 1956 delete test_context_; |
1957 owner_->set_function_state(outer_); | 1957 owner_->set_function_state(outer_); |
1958 } | 1958 } |
1959 | 1959 |
1960 | 1960 |
1961 // Implementation of utility classes to represent an expression's context in | 1961 // Implementation of utility classes to represent an expression's context in |
1962 // the AST. | 1962 // the AST. |
1963 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) | 1963 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) |
1964 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { | 1964 : owner_(owner), |
1965 kind_(kind), | |
1966 outer_(owner->ast_context()), | |
1967 for_typeof_(false) { | |
1965 owner->set_ast_context(this); // Push. | 1968 owner->set_ast_context(this); // Push. |
1966 #ifdef DEBUG | 1969 #ifdef DEBUG |
1967 original_length_ = owner->environment()->length(); | 1970 original_length_ = owner->environment()->length(); |
1968 #endif | 1971 #endif |
1969 } | 1972 } |
1970 | 1973 |
1971 | 1974 |
1972 AstContext::~AstContext() { | 1975 AstContext::~AstContext() { |
1973 owner_->set_ast_context(outer_); // Pop. | 1976 owner_->set_ast_context(outer_); // Pop. |
1974 } | 1977 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2098 Visit(expr); | 2101 Visit(expr); |
2099 } | 2102 } |
2100 | 2103 |
2101 | 2104 |
2102 void HGraphBuilder::VisitForValue(Expression* expr) { | 2105 void HGraphBuilder::VisitForValue(Expression* expr) { |
2103 ValueContext for_value(this); | 2106 ValueContext for_value(this); |
2104 Visit(expr); | 2107 Visit(expr); |
2105 } | 2108 } |
2106 | 2109 |
2107 | 2110 |
2111 void HGraphBuilder::VisitForTypeOf(Expression* expr) { | |
2112 ValueContext for_value(this); | |
2113 for_value.set_for_typeof(true); | |
2114 Visit(expr); | |
2115 } | |
2116 | |
2117 | |
2118 | |
2108 void HGraphBuilder::VisitForControl(Expression* expr, | 2119 void HGraphBuilder::VisitForControl(Expression* expr, |
2109 HBasicBlock* true_block, | 2120 HBasicBlock* true_block, |
2110 HBasicBlock* false_block) { | 2121 HBasicBlock* false_block) { |
2111 TestContext for_test(this, true_block, false_block); | 2122 TestContext for_test(this, true_block, false_block); |
2112 Visit(expr); | 2123 Visit(expr); |
2113 } | 2124 } |
2114 | 2125 |
2115 | 2126 |
2116 void HGraphBuilder::VisitArgument(Expression* expr) { | 2127 void HGraphBuilder::VisitArgument(Expression* expr) { |
2117 VISIT_FOR_VALUE(expr); | 2128 VISIT_FOR_VALUE(expr); |
(...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2790 CHECK_BAILOUT; | 2801 CHECK_BAILOUT; |
2791 | 2802 |
2792 if (!ast_context()->IsTest()) { | 2803 if (!ast_context()->IsTest()) { |
2793 HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); | 2804 HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); |
2794 set_current_block(join); | 2805 set_current_block(join); |
2795 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 2806 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
2796 } | 2807 } |
2797 } | 2808 } |
2798 | 2809 |
2799 | 2810 |
2800 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, | 2811 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( |
2801 LookupResult* lookup, | 2812 Variable* var, LookupResult* lookup, bool is_store) { |
2802 bool is_store) { | |
2803 if (var->is_this()) { | 2813 if (var->is_this()) { |
2804 BAILOUT("global this reference"); | 2814 return kUseGeneric; |
fschneider
2011/03/16 10:28:18
I'd move this into the same line as the if-stateme
Søren Thygesen Gjesse
2011/03/17 07:52:27
Done.
| |
2805 } | 2815 } |
2806 if (!info()->has_global_object()) { | 2816 if (!info()->has_global_object()) { |
2807 BAILOUT("no global object to optimize VariableProxy"); | 2817 return kUseGeneric; |
2808 } | 2818 } |
2809 Handle<GlobalObject> global(info()->global_object()); | 2819 Handle<GlobalObject> global(info()->global_object()); |
2810 global->Lookup(*var->name(), lookup); | 2820 global->Lookup(*var->name(), lookup); |
2811 if (!lookup->IsProperty()) { | 2821 if (!lookup->IsProperty()) { |
2812 BAILOUT("global variable cell not yet introduced"); | 2822 return kUseGeneric; |
2813 } | 2823 } |
2814 if (lookup->type() != NORMAL) { | 2824 if (lookup->type() != NORMAL) { |
2815 BAILOUT("global variable has accessors"); | 2825 return kUseGeneric; |
2816 } | 2826 } |
2817 if (is_store && lookup->IsReadOnly()) { | 2827 if (is_store && lookup->IsReadOnly()) { |
2818 BAILOUT("read-only global variable"); | 2828 return kUseGeneric; |
2819 } | 2829 } |
2820 if (lookup->holder() != *global) { | 2830 if (lookup->holder() != *global) { |
2821 BAILOUT("global property on prototype of global object"); | 2831 return kUseGeneric; |
2822 } | 2832 } |
2833 | |
2834 return kUseCell; | |
2823 } | 2835 } |
2824 | 2836 |
2825 | 2837 |
2826 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { | 2838 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
2827 ASSERT(var->IsContextSlot()); | 2839 ASSERT(var->IsContextSlot()); |
2828 HInstruction* context = new HContext; | 2840 HInstruction* context = new HContext; |
2829 AddInstruction(context); | 2841 AddInstruction(context); |
2830 int length = info()->scope()->ContextChainLength(var->scope()); | 2842 int length = info()->scope()->ContextChainLength(var->scope()); |
2831 while (length-- > 0) { | 2843 while (length-- > 0) { |
2832 context = new HOuterContext(context); | 2844 context = new HOuterContext(context); |
(...skipping 15 matching lines...) Expand all Loading... | |
2848 } else if (variable->IsContextSlot()) { | 2860 } else if (variable->IsContextSlot()) { |
2849 if (variable->mode() == Variable::CONST) { | 2861 if (variable->mode() == Variable::CONST) { |
2850 BAILOUT("reference to const context slot"); | 2862 BAILOUT("reference to const context slot"); |
2851 } | 2863 } |
2852 HValue* context = BuildContextChainWalk(variable); | 2864 HValue* context = BuildContextChainWalk(variable); |
2853 int index = variable->AsSlot()->index(); | 2865 int index = variable->AsSlot()->index(); |
2854 HLoadContextSlot* instr = new HLoadContextSlot(context, index); | 2866 HLoadContextSlot* instr = new HLoadContextSlot(context, index); |
2855 ast_context()->ReturnInstruction(instr, expr->id()); | 2867 ast_context()->ReturnInstruction(instr, expr->id()); |
2856 } else if (variable->is_global()) { | 2868 } else if (variable->is_global()) { |
2857 LookupResult lookup; | 2869 LookupResult lookup; |
2858 LookupGlobalPropertyCell(variable, &lookup, false); | 2870 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); |
2859 CHECK_BAILOUT; | |
2860 | 2871 |
2861 Handle<GlobalObject> global(info()->global_object()); | 2872 if (type == kUseCell && |
2862 // TODO(3039103): Handle global property load through an IC call when access | 2873 info()->global_object()->IsAccessCheckNeeded()) { |
2863 // checks are enabled. | 2874 type = kUseGeneric; |
2864 if (global->IsAccessCheckNeeded()) { | |
2865 BAILOUT("global object requires access check"); | |
2866 } | 2875 } |
2867 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 2876 |
2868 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 2877 if (type == kUseCell) { |
2869 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); | 2878 Handle<GlobalObject> global(info()->global_object()); |
2870 ast_context()->ReturnInstruction(instr, expr->id()); | 2879 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
2880 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | |
2881 HLoadGlobalCell* instr = new HLoadGlobalCell(cell, check_hole); | |
2882 ast_context()->ReturnInstruction(instr, expr->id()); | |
2883 } else { | |
2884 HContext* context = new HContext; | |
2885 AddInstruction(context); | |
2886 HLoadGlobalGeneric* instr = | |
2887 new HLoadGlobalGeneric( | |
2888 context, variable->name(), ast_context()->is_for_typeof()); | |
2889 ast_context()->ReturnInstruction(instr, expr->id()); | |
2890 } | |
2871 } else { | 2891 } else { |
2872 BAILOUT("reference to a variable which requires dynamic lookup"); | 2892 BAILOUT("reference to a variable which requires dynamic lookup"); |
2873 } | 2893 } |
2874 } | 2894 } |
2875 | 2895 |
2876 | 2896 |
2877 void HGraphBuilder::VisitLiteral(Literal* expr) { | 2897 void HGraphBuilder::VisitLiteral(Literal* expr) { |
2878 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); | 2898 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); |
2879 ast_context()->ReturnInstruction(instr, expr->id()); | 2899 ast_context()->ReturnInstruction(instr, expr->id()); |
2880 } | 2900 } |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3217 | 3237 |
3218 | 3238 |
3219 // Because not every expression has a position and there is not common | 3239 // Because not every expression has a position and there is not common |
3220 // superclass of Assignment and CountOperation, we cannot just pass the | 3240 // superclass of Assignment and CountOperation, we cannot just pass the |
3221 // owning expression instead of position and ast_id separately. | 3241 // owning expression instead of position and ast_id separately. |
3222 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 3242 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
3223 HValue* value, | 3243 HValue* value, |
3224 int position, | 3244 int position, |
3225 int ast_id) { | 3245 int ast_id) { |
3226 LookupResult lookup; | 3246 LookupResult lookup; |
3227 LookupGlobalPropertyCell(var, &lookup, true); | 3247 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
3228 CHECK_BAILOUT; | 3248 if (type == kUseCell) { |
3229 | 3249 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
3230 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 3250 Handle<GlobalObject> global(info()->global_object()); |
3231 Handle<GlobalObject> global(info()->global_object()); | 3251 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
3232 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3252 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); |
3233 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); | 3253 instr->set_position(position); |
3234 instr->set_position(position); | 3254 AddInstruction(instr); |
3235 AddInstruction(instr); | 3255 if (instr->HasSideEffects()) AddSimulate(ast_id); |
3236 if (instr->HasSideEffects()) AddSimulate(ast_id); | 3256 } else { |
3257 BAILOUT("global store only supported for cells"); | |
3258 } | |
3237 } | 3259 } |
3238 | 3260 |
3239 | 3261 |
3240 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 3262 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
3241 Expression* target = expr->target(); | 3263 Expression* target = expr->target(); |
3242 VariableProxy* proxy = target->AsVariableProxy(); | 3264 VariableProxy* proxy = target->AsVariableProxy(); |
3243 Variable* var = proxy->AsVariable(); | 3265 Variable* var = proxy->AsVariable(); |
3244 Property* prop = target->AsProperty(); | 3266 Property* prop = target->AsProperty(); |
3245 ASSERT(var == NULL || prop == NULL); | 3267 ASSERT(var == NULL || prop == NULL); |
3246 | 3268 |
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4321 if (!global_call) { | 4343 if (!global_call) { |
4322 ++argument_count; | 4344 ++argument_count; |
4323 VISIT_FOR_VALUE(expr->expression()); | 4345 VISIT_FOR_VALUE(expr->expression()); |
4324 } | 4346 } |
4325 | 4347 |
4326 if (global_call) { | 4348 if (global_call) { |
4327 bool known_global_function = false; | 4349 bool known_global_function = false; |
4328 // If there is a global property cell for the name at compile time and | 4350 // If there is a global property cell for the name at compile time and |
4329 // access check is not enabled we assume that the function will not change | 4351 // access check is not enabled we assume that the function will not change |
4330 // and generate optimized code for calling the function. | 4352 // and generate optimized code for calling the function. |
4331 if (info()->has_global_object() && | 4353 LookupResult lookup; |
4354 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | |
4355 if (type == kUseCell && | |
4332 !info()->global_object()->IsAccessCheckNeeded()) { | 4356 !info()->global_object()->IsAccessCheckNeeded()) { |
4333 Handle<GlobalObject> global(info()->global_object()); | 4357 Handle<GlobalObject> global(info()->global_object()); |
4334 known_global_function = expr->ComputeGlobalTarget(global, var->name()); | 4358 known_global_function = expr->ComputeGlobalTarget(global, lookup); |
4335 } | 4359 } |
4336 if (known_global_function) { | 4360 if (known_global_function) { |
4337 // Push the global object instead of the global receiver because | 4361 // Push the global object instead of the global receiver because |
4338 // code generated by the full code generator expects it. | 4362 // code generated by the full code generator expects it. |
4339 HContext* context = new HContext; | 4363 HContext* context = new HContext; |
4340 HGlobalObject* global_object = new HGlobalObject(context); | 4364 HGlobalObject* global_object = new HGlobalObject(context); |
4341 AddInstruction(context); | 4365 AddInstruction(context); |
4342 PushAndAdd(global_object); | 4366 PushAndAdd(global_object); |
4343 VisitExpressions(expr->arguments()); | 4367 VisitExpressions(expr->arguments()); |
4344 CHECK_BAILOUT; | 4368 CHECK_BAILOUT; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4543 break; | 4567 break; |
4544 case Token::SUB: | 4568 case Token::SUB: |
4545 instr = new HMul(graph_->GetConstantMinus1(), value); | 4569 instr = new HMul(graph_->GetConstantMinus1(), value); |
4546 break; | 4570 break; |
4547 default: | 4571 default: |
4548 UNREACHABLE(); | 4572 UNREACHABLE(); |
4549 break; | 4573 break; |
4550 } | 4574 } |
4551 ast_context()->ReturnInstruction(instr, expr->id()); | 4575 ast_context()->ReturnInstruction(instr, expr->id()); |
4552 } else if (op == Token::TYPEOF) { | 4576 } else if (op == Token::TYPEOF) { |
4553 VISIT_FOR_VALUE(expr->expression()); | 4577 VisitForTypeOf(expr); |
4578 if (HasStackOverflow()) return; | |
4554 HValue* value = Pop(); | 4579 HValue* value = Pop(); |
4555 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); | 4580 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); |
4556 } else { | 4581 } else { |
4557 BAILOUT("Value: unsupported unary operation"); | 4582 BAILOUT("Value: unsupported unary operation"); |
4558 } | 4583 } |
4559 } | 4584 } |
4560 | 4585 |
4561 | 4586 |
4562 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { | 4587 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { |
4563 // IncrementOperation is never visited by the visitor. It only | 4588 // IncrementOperation is never visited by the visitor. It only |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4928 ast_context()->ReturnInstruction(instr, expr->id()); | 4953 ast_context()->ReturnInstruction(instr, expr->id()); |
4929 return; | 4954 return; |
4930 } | 4955 } |
4931 | 4956 |
4932 // Check for the pattern: typeof <expression> == <string literal>. | 4957 // Check for the pattern: typeof <expression> == <string literal>. |
4933 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); | 4958 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); |
4934 Literal* right_literal = expr->right()->AsLiteral(); | 4959 Literal* right_literal = expr->right()->AsLiteral(); |
4935 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && | 4960 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
4936 left_unary != NULL && left_unary->op() == Token::TYPEOF && | 4961 left_unary != NULL && left_unary->op() == Token::TYPEOF && |
4937 right_literal != NULL && right_literal->handle()->IsString()) { | 4962 right_literal != NULL && right_literal->handle()->IsString()) { |
4938 VISIT_FOR_VALUE(left_unary->expression()); | 4963 VisitForTypeOf(expr); |
4964 if (HasStackOverflow()) return; | |
4939 HValue* left = Pop(); | 4965 HValue* left = Pop(); |
4940 HInstruction* instr = new HTypeofIs(left, | 4966 HInstruction* instr = new HTypeofIs(left, |
4941 Handle<String>::cast(right_literal->handle())); | 4967 Handle<String>::cast(right_literal->handle())); |
4942 instr->set_position(expr->position()); | 4968 instr->set_position(expr->position()); |
4943 ast_context()->ReturnInstruction(instr, expr->id()); | 4969 ast_context()->ReturnInstruction(instr, expr->id()); |
4944 return; | 4970 return; |
4945 } | 4971 } |
4946 | 4972 |
4947 VISIT_FOR_VALUE(expr->left()); | 4973 VISIT_FOR_VALUE(expr->left()); |
4948 VISIT_FOR_VALUE(expr->right()); | 4974 VISIT_FOR_VALUE(expr->right()); |
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5925 } | 5951 } |
5926 } | 5952 } |
5927 | 5953 |
5928 #ifdef DEBUG | 5954 #ifdef DEBUG |
5929 if (graph_ != NULL) graph_->Verify(); | 5955 if (graph_ != NULL) graph_->Verify(); |
5930 if (allocator_ != NULL) allocator_->Verify(); | 5956 if (allocator_ != NULL) allocator_->Verify(); |
5931 #endif | 5957 #endif |
5932 } | 5958 } |
5933 | 5959 |
5934 } } // namespace v8::internal | 5960 } } // namespace v8::internal |
OLD | NEW |