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) { | 2813 if (var->is_this() || !info()->has_global_object()) { |
2803 if (var->is_this()) { | 2814 return kUseGeneric; |
2804 BAILOUT("global this reference"); | |
2805 } | |
2806 if (!info()->has_global_object()) { | |
2807 BAILOUT("no global object to optimize VariableProxy"); | |
2808 } | 2815 } |
2809 Handle<GlobalObject> global(info()->global_object()); | 2816 Handle<GlobalObject> global(info()->global_object()); |
2810 global->Lookup(*var->name(), lookup); | 2817 global->Lookup(*var->name(), lookup); |
2811 if (!lookup->IsProperty()) { | 2818 if (!lookup->IsProperty() || |
2812 BAILOUT("global variable cell not yet introduced"); | 2819 lookup->type() != NORMAL || |
| 2820 (is_store && lookup->IsReadOnly()) || |
| 2821 lookup->holder() != *global) { |
| 2822 return kUseGeneric; |
2813 } | 2823 } |
2814 if (lookup->type() != NORMAL) { | 2824 |
2815 BAILOUT("global variable has accessors"); | 2825 return kUseCell; |
2816 } | |
2817 if (is_store && lookup->IsReadOnly()) { | |
2818 BAILOUT("read-only global variable"); | |
2819 } | |
2820 if (lookup->holder() != *global) { | |
2821 BAILOUT("global property on prototype of global object"); | |
2822 } | |
2823 } | 2826 } |
2824 | 2827 |
2825 | 2828 |
2826 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { | 2829 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
2827 ASSERT(var->IsContextSlot()); | 2830 ASSERT(var->IsContextSlot()); |
2828 HInstruction* context = new HContext; | 2831 HInstruction* context = new HContext; |
2829 AddInstruction(context); | 2832 AddInstruction(context); |
2830 int length = info()->scope()->ContextChainLength(var->scope()); | 2833 int length = info()->scope()->ContextChainLength(var->scope()); |
2831 while (length-- > 0) { | 2834 while (length-- > 0) { |
2832 context = new HOuterContext(context); | 2835 context = new HOuterContext(context); |
(...skipping 15 matching lines...) Expand all Loading... |
2848 } else if (variable->IsContextSlot()) { | 2851 } else if (variable->IsContextSlot()) { |
2849 if (variable->mode() == Variable::CONST) { | 2852 if (variable->mode() == Variable::CONST) { |
2850 BAILOUT("reference to const context slot"); | 2853 BAILOUT("reference to const context slot"); |
2851 } | 2854 } |
2852 HValue* context = BuildContextChainWalk(variable); | 2855 HValue* context = BuildContextChainWalk(variable); |
2853 int index = variable->AsSlot()->index(); | 2856 int index = variable->AsSlot()->index(); |
2854 HLoadContextSlot* instr = new HLoadContextSlot(context, index); | 2857 HLoadContextSlot* instr = new HLoadContextSlot(context, index); |
2855 ast_context()->ReturnInstruction(instr, expr->id()); | 2858 ast_context()->ReturnInstruction(instr, expr->id()); |
2856 } else if (variable->is_global()) { | 2859 } else if (variable->is_global()) { |
2857 LookupResult lookup; | 2860 LookupResult lookup; |
2858 LookupGlobalPropertyCell(variable, &lookup, false); | 2861 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); |
2859 CHECK_BAILOUT; | |
2860 | 2862 |
2861 Handle<GlobalObject> global(info()->global_object()); | 2863 if (type == kUseCell && |
2862 // TODO(3039103): Handle global property load through an IC call when access | 2864 info()->global_object()->IsAccessCheckNeeded()) { |
2863 // checks are enabled. | 2865 type = kUseGeneric; |
2864 if (global->IsAccessCheckNeeded()) { | |
2865 BAILOUT("global object requires access check"); | |
2866 } | 2866 } |
2867 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 2867 |
2868 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 2868 if (type == kUseCell) { |
2869 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); | 2869 Handle<GlobalObject> global(info()->global_object()); |
2870 ast_context()->ReturnInstruction(instr, expr->id()); | 2870 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 2871 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| 2872 HLoadGlobalCell* instr = new HLoadGlobalCell(cell, check_hole); |
| 2873 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2874 } else { |
| 2875 HContext* context = new HContext; |
| 2876 AddInstruction(context); |
| 2877 HGlobalObject* global_object = new HGlobalObject(context); |
| 2878 AddInstruction(global_object); |
| 2879 HLoadGlobalGeneric* instr = |
| 2880 new HLoadGlobalGeneric(context, |
| 2881 global_object, |
| 2882 variable->name(), |
| 2883 ast_context()->is_for_typeof()); |
| 2884 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2885 } |
2871 } else { | 2886 } else { |
2872 BAILOUT("reference to a variable which requires dynamic lookup"); | 2887 BAILOUT("reference to a variable which requires dynamic lookup"); |
2873 } | 2888 } |
2874 } | 2889 } |
2875 | 2890 |
2876 | 2891 |
2877 void HGraphBuilder::VisitLiteral(Literal* expr) { | 2892 void HGraphBuilder::VisitLiteral(Literal* expr) { |
2878 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); | 2893 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); |
2879 ast_context()->ReturnInstruction(instr, expr->id()); | 2894 ast_context()->ReturnInstruction(instr, expr->id()); |
2880 } | 2895 } |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3217 | 3232 |
3218 | 3233 |
3219 // Because not every expression has a position and there is not common | 3234 // Because not every expression has a position and there is not common |
3220 // superclass of Assignment and CountOperation, we cannot just pass the | 3235 // superclass of Assignment and CountOperation, we cannot just pass the |
3221 // owning expression instead of position and ast_id separately. | 3236 // owning expression instead of position and ast_id separately. |
3222 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 3237 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
3223 HValue* value, | 3238 HValue* value, |
3224 int position, | 3239 int position, |
3225 int ast_id) { | 3240 int ast_id) { |
3226 LookupResult lookup; | 3241 LookupResult lookup; |
3227 LookupGlobalPropertyCell(var, &lookup, true); | 3242 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
3228 CHECK_BAILOUT; | 3243 if (type == kUseCell) { |
3229 | 3244 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
3230 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 3245 Handle<GlobalObject> global(info()->global_object()); |
3231 Handle<GlobalObject> global(info()->global_object()); | 3246 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
3232 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3247 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); |
3233 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); | 3248 instr->set_position(position); |
3234 instr->set_position(position); | 3249 AddInstruction(instr); |
3235 AddInstruction(instr); | 3250 if (instr->HasSideEffects()) AddSimulate(ast_id); |
3236 if (instr->HasSideEffects()) AddSimulate(ast_id); | 3251 } else { |
| 3252 BAILOUT("global store only supported for cells"); |
| 3253 } |
3237 } | 3254 } |
3238 | 3255 |
3239 | 3256 |
3240 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 3257 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
3241 Expression* target = expr->target(); | 3258 Expression* target = expr->target(); |
3242 VariableProxy* proxy = target->AsVariableProxy(); | 3259 VariableProxy* proxy = target->AsVariableProxy(); |
3243 Variable* var = proxy->AsVariable(); | 3260 Variable* var = proxy->AsVariable(); |
3244 Property* prop = target->AsProperty(); | 3261 Property* prop = target->AsProperty(); |
3245 ASSERT(var == NULL || prop == NULL); | 3262 ASSERT(var == NULL || prop == NULL); |
3246 | 3263 |
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4321 if (!global_call) { | 4338 if (!global_call) { |
4322 ++argument_count; | 4339 ++argument_count; |
4323 VISIT_FOR_VALUE(expr->expression()); | 4340 VISIT_FOR_VALUE(expr->expression()); |
4324 } | 4341 } |
4325 | 4342 |
4326 if (global_call) { | 4343 if (global_call) { |
4327 bool known_global_function = false; | 4344 bool known_global_function = false; |
4328 // If there is a global property cell for the name at compile time and | 4345 // 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 | 4346 // access check is not enabled we assume that the function will not change |
4330 // and generate optimized code for calling the function. | 4347 // and generate optimized code for calling the function. |
4331 if (info()->has_global_object() && | 4348 LookupResult lookup; |
| 4349 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| 4350 if (type == kUseCell && |
4332 !info()->global_object()->IsAccessCheckNeeded()) { | 4351 !info()->global_object()->IsAccessCheckNeeded()) { |
4333 Handle<GlobalObject> global(info()->global_object()); | 4352 Handle<GlobalObject> global(info()->global_object()); |
4334 known_global_function = expr->ComputeGlobalTarget(global, var->name()); | 4353 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
4335 } | 4354 } |
4336 if (known_global_function) { | 4355 if (known_global_function) { |
4337 // Push the global object instead of the global receiver because | 4356 // Push the global object instead of the global receiver because |
4338 // code generated by the full code generator expects it. | 4357 // code generated by the full code generator expects it. |
4339 HContext* context = new HContext; | 4358 HContext* context = new HContext; |
4340 HGlobalObject* global_object = new HGlobalObject(context); | 4359 HGlobalObject* global_object = new HGlobalObject(context); |
4341 AddInstruction(context); | 4360 AddInstruction(context); |
4342 PushAndAdd(global_object); | 4361 PushAndAdd(global_object); |
4343 VisitExpressions(expr->arguments()); | 4362 VisitExpressions(expr->arguments()); |
4344 CHECK_BAILOUT; | 4363 CHECK_BAILOUT; |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4543 break; | 4562 break; |
4544 case Token::SUB: | 4563 case Token::SUB: |
4545 instr = new HMul(graph_->GetConstantMinus1(), value); | 4564 instr = new HMul(graph_->GetConstantMinus1(), value); |
4546 break; | 4565 break; |
4547 default: | 4566 default: |
4548 UNREACHABLE(); | 4567 UNREACHABLE(); |
4549 break; | 4568 break; |
4550 } | 4569 } |
4551 ast_context()->ReturnInstruction(instr, expr->id()); | 4570 ast_context()->ReturnInstruction(instr, expr->id()); |
4552 } else if (op == Token::TYPEOF) { | 4571 } else if (op == Token::TYPEOF) { |
4553 VISIT_FOR_VALUE(expr->expression()); | 4572 VisitForTypeOf(expr); |
| 4573 if (HasStackOverflow()) return; |
4554 HValue* value = Pop(); | 4574 HValue* value = Pop(); |
4555 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); | 4575 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); |
4556 } else { | 4576 } else { |
4557 BAILOUT("Value: unsupported unary operation"); | 4577 BAILOUT("Value: unsupported unary operation"); |
4558 } | 4578 } |
4559 } | 4579 } |
4560 | 4580 |
4561 | 4581 |
4562 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { | 4582 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { |
4563 // IncrementOperation is never visited by the visitor. It only | 4583 // 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()); | 4948 ast_context()->ReturnInstruction(instr, expr->id()); |
4929 return; | 4949 return; |
4930 } | 4950 } |
4931 | 4951 |
4932 // Check for the pattern: typeof <expression> == <string literal>. | 4952 // Check for the pattern: typeof <expression> == <string literal>. |
4933 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); | 4953 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); |
4934 Literal* right_literal = expr->right()->AsLiteral(); | 4954 Literal* right_literal = expr->right()->AsLiteral(); |
4935 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && | 4955 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
4936 left_unary != NULL && left_unary->op() == Token::TYPEOF && | 4956 left_unary != NULL && left_unary->op() == Token::TYPEOF && |
4937 right_literal != NULL && right_literal->handle()->IsString()) { | 4957 right_literal != NULL && right_literal->handle()->IsString()) { |
4938 VISIT_FOR_VALUE(left_unary->expression()); | 4958 VisitForTypeOf(expr); |
| 4959 if (HasStackOverflow()) return; |
4939 HValue* left = Pop(); | 4960 HValue* left = Pop(); |
4940 HInstruction* instr = new HTypeofIs(left, | 4961 HInstruction* instr = new HTypeofIs(left, |
4941 Handle<String>::cast(right_literal->handle())); | 4962 Handle<String>::cast(right_literal->handle())); |
4942 instr->set_position(expr->position()); | 4963 instr->set_position(expr->position()); |
4943 ast_context()->ReturnInstruction(instr, expr->id()); | 4964 ast_context()->ReturnInstruction(instr, expr->id()); |
4944 return; | 4965 return; |
4945 } | 4966 } |
4946 | 4967 |
4947 VISIT_FOR_VALUE(expr->left()); | 4968 VISIT_FOR_VALUE(expr->left()); |
4948 VISIT_FOR_VALUE(expr->right()); | 4969 VISIT_FOR_VALUE(expr->right()); |
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5925 } | 5946 } |
5926 } | 5947 } |
5927 | 5948 |
5928 #ifdef DEBUG | 5949 #ifdef DEBUG |
5929 if (graph_ != NULL) graph_->Verify(); | 5950 if (graph_ != NULL) graph_->Verify(); |
5930 if (allocator_ != NULL) allocator_->Verify(); | 5951 if (allocator_ != NULL) allocator_->Verify(); |
5931 #endif | 5952 #endif |
5932 } | 5953 } |
5933 | 5954 |
5934 } } // namespace v8::internal | 5955 } } // namespace v8::internal |
OLD | NEW |