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), | 1964 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { |
1965 kind_(kind), | |
1966 outer_(owner->ast_context()), | |
1967 for_typeof_(false) { | |
1968 owner->set_ast_context(this); // Push. | 1965 owner->set_ast_context(this); // Push. |
1969 #ifdef DEBUG | 1966 #ifdef DEBUG |
1970 original_length_ = owner->environment()->length(); | 1967 original_length_ = owner->environment()->length(); |
1971 #endif | 1968 #endif |
1972 } | 1969 } |
1973 | 1970 |
1974 | 1971 |
1975 AstContext::~AstContext() { | 1972 AstContext::~AstContext() { |
1976 owner_->set_ast_context(outer_); // Pop. | 1973 owner_->set_ast_context(outer_); // Pop. |
1977 } | 1974 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2101 Visit(expr); | 2098 Visit(expr); |
2102 } | 2099 } |
2103 | 2100 |
2104 | 2101 |
2105 void HGraphBuilder::VisitForValue(Expression* expr) { | 2102 void HGraphBuilder::VisitForValue(Expression* expr) { |
2106 ValueContext for_value(this); | 2103 ValueContext for_value(this); |
2107 Visit(expr); | 2104 Visit(expr); |
2108 } | 2105 } |
2109 | 2106 |
2110 | 2107 |
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 | |
2119 void HGraphBuilder::VisitForControl(Expression* expr, | 2108 void HGraphBuilder::VisitForControl(Expression* expr, |
2120 HBasicBlock* true_block, | 2109 HBasicBlock* true_block, |
2121 HBasicBlock* false_block) { | 2110 HBasicBlock* false_block) { |
2122 TestContext for_test(this, true_block, false_block); | 2111 TestContext for_test(this, true_block, false_block); |
2123 Visit(expr); | 2112 Visit(expr); |
2124 } | 2113 } |
2125 | 2114 |
2126 | 2115 |
2127 void HGraphBuilder::VisitArgument(Expression* expr) { | 2116 void HGraphBuilder::VisitArgument(Expression* expr) { |
2128 VISIT_FOR_VALUE(expr); | 2117 VISIT_FOR_VALUE(expr); |
(...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2801 CHECK_BAILOUT; | 2790 CHECK_BAILOUT; |
2802 | 2791 |
2803 if (!ast_context()->IsTest()) { | 2792 if (!ast_context()->IsTest()) { |
2804 HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); | 2793 HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); |
2805 set_current_block(join); | 2794 set_current_block(join); |
2806 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 2795 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
2807 } | 2796 } |
2808 } | 2797 } |
2809 | 2798 |
2810 | 2799 |
2811 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( | 2800 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, |
2812 Variable* var, LookupResult* lookup, bool is_store) { | 2801 LookupResult* lookup, |
2813 if (var->is_this() || !info()->has_global_object()) { | 2802 bool is_store) { |
2814 return kUseGeneric; | 2803 if (var->is_this()) { |
| 2804 BAILOUT("global this reference"); |
| 2805 } |
| 2806 if (!info()->has_global_object()) { |
| 2807 BAILOUT("no global object to optimize VariableProxy"); |
2815 } | 2808 } |
2816 Handle<GlobalObject> global(info()->global_object()); | 2809 Handle<GlobalObject> global(info()->global_object()); |
2817 global->Lookup(*var->name(), lookup); | 2810 global->Lookup(*var->name(), lookup); |
2818 if (!lookup->IsProperty() || | 2811 if (!lookup->IsProperty()) { |
2819 lookup->type() != NORMAL || | 2812 BAILOUT("global variable cell not yet introduced"); |
2820 (is_store && lookup->IsReadOnly()) || | |
2821 lookup->holder() != *global) { | |
2822 return kUseGeneric; | |
2823 } | 2813 } |
2824 | 2814 if (lookup->type() != NORMAL) { |
2825 return kUseCell; | 2815 BAILOUT("global variable has accessors"); |
| 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 } |
2826 } | 2823 } |
2827 | 2824 |
2828 | 2825 |
2829 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { | 2826 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
2830 ASSERT(var->IsContextSlot()); | 2827 ASSERT(var->IsContextSlot()); |
2831 HInstruction* context = new HContext; | 2828 HInstruction* context = new HContext; |
2832 AddInstruction(context); | 2829 AddInstruction(context); |
2833 int length = info()->scope()->ContextChainLength(var->scope()); | 2830 int length = info()->scope()->ContextChainLength(var->scope()); |
2834 while (length-- > 0) { | 2831 while (length-- > 0) { |
2835 context = new HOuterContext(context); | 2832 context = new HOuterContext(context); |
(...skipping 15 matching lines...) Expand all Loading... |
2851 } else if (variable->IsContextSlot()) { | 2848 } else if (variable->IsContextSlot()) { |
2852 if (variable->mode() == Variable::CONST) { | 2849 if (variable->mode() == Variable::CONST) { |
2853 BAILOUT("reference to const context slot"); | 2850 BAILOUT("reference to const context slot"); |
2854 } | 2851 } |
2855 HValue* context = BuildContextChainWalk(variable); | 2852 HValue* context = BuildContextChainWalk(variable); |
2856 int index = variable->AsSlot()->index(); | 2853 int index = variable->AsSlot()->index(); |
2857 HLoadContextSlot* instr = new HLoadContextSlot(context, index); | 2854 HLoadContextSlot* instr = new HLoadContextSlot(context, index); |
2858 ast_context()->ReturnInstruction(instr, expr->id()); | 2855 ast_context()->ReturnInstruction(instr, expr->id()); |
2859 } else if (variable->is_global()) { | 2856 } else if (variable->is_global()) { |
2860 LookupResult lookup; | 2857 LookupResult lookup; |
2861 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); | 2858 LookupGlobalPropertyCell(variable, &lookup, false); |
| 2859 CHECK_BAILOUT; |
2862 | 2860 |
2863 if (type == kUseCell && | 2861 Handle<GlobalObject> global(info()->global_object()); |
2864 info()->global_object()->IsAccessCheckNeeded()) { | 2862 // TODO(3039103): Handle global property load through an IC call when access |
2865 type = kUseGeneric; | 2863 // checks are enabled. |
| 2864 if (global->IsAccessCheckNeeded()) { |
| 2865 BAILOUT("global object requires access check"); |
2866 } | 2866 } |
2867 | 2867 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
2868 if (type == kUseCell) { | 2868 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
2869 Handle<GlobalObject> global(info()->global_object()); | 2869 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); |
2870 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 2870 ast_context()->ReturnInstruction(instr, expr->id()); |
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 } | |
2886 } else { | 2871 } else { |
2887 BAILOUT("reference to a variable which requires dynamic lookup"); | 2872 BAILOUT("reference to a variable which requires dynamic lookup"); |
2888 } | 2873 } |
2889 } | 2874 } |
2890 | 2875 |
2891 | 2876 |
2892 void HGraphBuilder::VisitLiteral(Literal* expr) { | 2877 void HGraphBuilder::VisitLiteral(Literal* expr) { |
2893 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); | 2878 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); |
2894 ast_context()->ReturnInstruction(instr, expr->id()); | 2879 ast_context()->ReturnInstruction(instr, expr->id()); |
2895 } | 2880 } |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3232 | 3217 |
3233 | 3218 |
3234 // Because not every expression has a position and there is not common | 3219 // Because not every expression has a position and there is not common |
3235 // superclass of Assignment and CountOperation, we cannot just pass the | 3220 // superclass of Assignment and CountOperation, we cannot just pass the |
3236 // owning expression instead of position and ast_id separately. | 3221 // owning expression instead of position and ast_id separately. |
3237 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 3222 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
3238 HValue* value, | 3223 HValue* value, |
3239 int position, | 3224 int position, |
3240 int ast_id) { | 3225 int ast_id) { |
3241 LookupResult lookup; | 3226 LookupResult lookup; |
3242 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 3227 LookupGlobalPropertyCell(var, &lookup, true); |
3243 if (type == kUseCell) { | 3228 CHECK_BAILOUT; |
3244 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 3229 |
3245 Handle<GlobalObject> global(info()->global_object()); | 3230 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
3246 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3231 Handle<GlobalObject> global(info()->global_object()); |
3247 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); | 3232 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
3248 instr->set_position(position); | 3233 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); |
3249 AddInstruction(instr); | 3234 instr->set_position(position); |
3250 if (instr->HasSideEffects()) AddSimulate(ast_id); | 3235 AddInstruction(instr); |
3251 } else { | 3236 if (instr->HasSideEffects()) AddSimulate(ast_id); |
3252 BAILOUT("global store only supported for cells"); | |
3253 } | |
3254 } | 3237 } |
3255 | 3238 |
3256 | 3239 |
3257 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 3240 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
3258 Expression* target = expr->target(); | 3241 Expression* target = expr->target(); |
3259 VariableProxy* proxy = target->AsVariableProxy(); | 3242 VariableProxy* proxy = target->AsVariableProxy(); |
3260 Variable* var = proxy->AsVariable(); | 3243 Variable* var = proxy->AsVariable(); |
3261 Property* prop = target->AsProperty(); | 3244 Property* prop = target->AsProperty(); |
3262 ASSERT(var == NULL || prop == NULL); | 3245 ASSERT(var == NULL || prop == NULL); |
3263 | 3246 |
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4338 if (!global_call) { | 4321 if (!global_call) { |
4339 ++argument_count; | 4322 ++argument_count; |
4340 VISIT_FOR_VALUE(expr->expression()); | 4323 VISIT_FOR_VALUE(expr->expression()); |
4341 } | 4324 } |
4342 | 4325 |
4343 if (global_call) { | 4326 if (global_call) { |
4344 bool known_global_function = false; | 4327 bool known_global_function = false; |
4345 // If there is a global property cell for the name at compile time and | 4328 // If there is a global property cell for the name at compile time and |
4346 // access check is not enabled we assume that the function will not change | 4329 // access check is not enabled we assume that the function will not change |
4347 // and generate optimized code for calling the function. | 4330 // and generate optimized code for calling the function. |
4348 LookupResult lookup; | 4331 if (info()->has_global_object() && |
4349 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | |
4350 if (type == kUseCell && | |
4351 !info()->global_object()->IsAccessCheckNeeded()) { | 4332 !info()->global_object()->IsAccessCheckNeeded()) { |
4352 Handle<GlobalObject> global(info()->global_object()); | 4333 Handle<GlobalObject> global(info()->global_object()); |
4353 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 4334 known_global_function = expr->ComputeGlobalTarget(global, var->name()); |
4354 } | 4335 } |
4355 if (known_global_function) { | 4336 if (known_global_function) { |
4356 // Push the global object instead of the global receiver because | 4337 // Push the global object instead of the global receiver because |
4357 // code generated by the full code generator expects it. | 4338 // code generated by the full code generator expects it. |
4358 HContext* context = new HContext; | 4339 HContext* context = new HContext; |
4359 HGlobalObject* global_object = new HGlobalObject(context); | 4340 HGlobalObject* global_object = new HGlobalObject(context); |
4360 AddInstruction(context); | 4341 AddInstruction(context); |
4361 PushAndAdd(global_object); | 4342 PushAndAdd(global_object); |
4362 VisitExpressions(expr->arguments()); | 4343 VisitExpressions(expr->arguments()); |
4363 CHECK_BAILOUT; | 4344 CHECK_BAILOUT; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4546 HBasicBlock* join = | 4527 HBasicBlock* join = |
4547 CreateJoin(materialize_false, materialize_true, expr->id()); | 4528 CreateJoin(materialize_false, materialize_true, expr->id()); |
4548 set_current_block(join); | 4529 set_current_block(join); |
4549 ast_context()->ReturnValue(Pop()); | 4530 ast_context()->ReturnValue(Pop()); |
4550 } else { | 4531 } else { |
4551 ASSERT(ast_context()->IsEffect()); | 4532 ASSERT(ast_context()->IsEffect()); |
4552 VisitForEffect(expr->expression()); | 4533 VisitForEffect(expr->expression()); |
4553 } | 4534 } |
4554 | 4535 |
4555 } else if (op == Token::TYPEOF) { | 4536 } else if (op == Token::TYPEOF) { |
4556 VisitForTypeOf(expr->expression()); | 4537 VISIT_FOR_VALUE(expr->expression()); |
4557 if (HasStackOverflow()) return; | |
4558 HValue* value = Pop(); | 4538 HValue* value = Pop(); |
4559 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); | 4539 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); |
4560 | 4540 |
4561 } else { | 4541 } else { |
4562 VISIT_FOR_VALUE(expr->expression()); | 4542 VISIT_FOR_VALUE(expr->expression()); |
4563 HValue* value = Pop(); | 4543 HValue* value = Pop(); |
4564 HInstruction* instr = NULL; | 4544 HInstruction* instr = NULL; |
4565 switch (op) { | 4545 switch (op) { |
4566 case Token::BIT_NOT: | 4546 case Token::BIT_NOT: |
4567 instr = new HBitNot(value); | 4547 instr = new HBitNot(value); |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4950 ast_context()->ReturnInstruction(instr, expr->id()); | 4930 ast_context()->ReturnInstruction(instr, expr->id()); |
4951 return; | 4931 return; |
4952 } | 4932 } |
4953 | 4933 |
4954 // Check for the pattern: typeof <expression> == <string literal>. | 4934 // Check for the pattern: typeof <expression> == <string literal>. |
4955 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); | 4935 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); |
4956 Literal* right_literal = expr->right()->AsLiteral(); | 4936 Literal* right_literal = expr->right()->AsLiteral(); |
4957 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && | 4937 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
4958 left_unary != NULL && left_unary->op() == Token::TYPEOF && | 4938 left_unary != NULL && left_unary->op() == Token::TYPEOF && |
4959 right_literal != NULL && right_literal->handle()->IsString()) { | 4939 right_literal != NULL && right_literal->handle()->IsString()) { |
4960 VisitForTypeOf(left_unary->expression()); | 4940 VISIT_FOR_VALUE(left_unary->expression()); |
4961 if (HasStackOverflow()) return; | |
4962 HValue* left = Pop(); | 4941 HValue* left = Pop(); |
4963 HInstruction* instr = new HTypeofIs(left, | 4942 HInstruction* instr = new HTypeofIs(left, |
4964 Handle<String>::cast(right_literal->handle())); | 4943 Handle<String>::cast(right_literal->handle())); |
4965 instr->set_position(expr->position()); | 4944 instr->set_position(expr->position()); |
4966 ast_context()->ReturnInstruction(instr, expr->id()); | 4945 ast_context()->ReturnInstruction(instr, expr->id()); |
4967 return; | 4946 return; |
4968 } | 4947 } |
4969 | 4948 |
4970 VISIT_FOR_VALUE(expr->left()); | 4949 VISIT_FOR_VALUE(expr->left()); |
4971 VISIT_FOR_VALUE(expr->right()); | 4950 VISIT_FOR_VALUE(expr->right()); |
(...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5948 } | 5927 } |
5949 } | 5928 } |
5950 | 5929 |
5951 #ifdef DEBUG | 5930 #ifdef DEBUG |
5952 if (graph_ != NULL) graph_->Verify(); | 5931 if (graph_ != NULL) graph_->Verify(); |
5953 if (allocator_ != NULL) allocator_->Verify(); | 5932 if (allocator_ != NULL) allocator_->Verify(); |
5954 #endif | 5933 #endif |
5955 } | 5934 } |
5956 | 5935 |
5957 } } // namespace v8::internal | 5936 } } // namespace v8::internal |
OLD | NEW |