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 1962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1973 | 1973 |
1974 FunctionState::~FunctionState() { | 1974 FunctionState::~FunctionState() { |
1975 delete test_context_; | 1975 delete test_context_; |
1976 owner_->set_function_state(outer_); | 1976 owner_->set_function_state(outer_); |
1977 } | 1977 } |
1978 | 1978 |
1979 | 1979 |
1980 // Implementation of utility classes to represent an expression's context in | 1980 // Implementation of utility classes to represent an expression's context in |
1981 // the AST. | 1981 // the AST. |
1982 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) | 1982 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) |
1983 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { | 1983 : owner_(owner), |
| 1984 kind_(kind), |
| 1985 outer_(owner->ast_context()), |
| 1986 for_typeof_(false) { |
1984 owner->set_ast_context(this); // Push. | 1987 owner->set_ast_context(this); // Push. |
1985 #ifdef DEBUG | 1988 #ifdef DEBUG |
1986 original_length_ = owner->environment()->length(); | 1989 original_length_ = owner->environment()->length(); |
1987 #endif | 1990 #endif |
1988 } | 1991 } |
1989 | 1992 |
1990 | 1993 |
1991 AstContext::~AstContext() { | 1994 AstContext::~AstContext() { |
1992 owner_->set_ast_context(outer_); // Pop. | 1995 owner_->set_ast_context(outer_); // Pop. |
1993 } | 1996 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2117 Visit(expr); | 2120 Visit(expr); |
2118 } | 2121 } |
2119 | 2122 |
2120 | 2123 |
2121 void HGraphBuilder::VisitForValue(Expression* expr) { | 2124 void HGraphBuilder::VisitForValue(Expression* expr) { |
2122 ValueContext for_value(this); | 2125 ValueContext for_value(this); |
2123 Visit(expr); | 2126 Visit(expr); |
2124 } | 2127 } |
2125 | 2128 |
2126 | 2129 |
| 2130 void HGraphBuilder::VisitForTypeOf(Expression* expr) { |
| 2131 ValueContext for_value(this); |
| 2132 for_value.set_for_typeof(true); |
| 2133 Visit(expr); |
| 2134 } |
| 2135 |
| 2136 |
| 2137 |
2127 void HGraphBuilder::VisitForControl(Expression* expr, | 2138 void HGraphBuilder::VisitForControl(Expression* expr, |
2128 HBasicBlock* true_block, | 2139 HBasicBlock* true_block, |
2129 HBasicBlock* false_block) { | 2140 HBasicBlock* false_block) { |
2130 TestContext for_test(this, true_block, false_block); | 2141 TestContext for_test(this, true_block, false_block); |
2131 Visit(expr); | 2142 Visit(expr); |
2132 } | 2143 } |
2133 | 2144 |
2134 | 2145 |
2135 void HGraphBuilder::VisitArgument(Expression* expr) { | 2146 void HGraphBuilder::VisitArgument(Expression* expr) { |
2136 VISIT_FOR_VALUE(expr); | 2147 VISIT_FOR_VALUE(expr); |
(...skipping 689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2826 CHECK_BAILOUT; | 2837 CHECK_BAILOUT; |
2827 | 2838 |
2828 if (!ast_context()->IsTest()) { | 2839 if (!ast_context()->IsTest()) { |
2829 HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); | 2840 HBasicBlock* join = CreateJoin(other, current_block(), expr->id()); |
2830 set_current_block(join); | 2841 set_current_block(join); |
2831 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 2842 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
2832 } | 2843 } |
2833 } | 2844 } |
2834 | 2845 |
2835 | 2846 |
2836 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, | 2847 HGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( |
2837 LookupResult* lookup, | 2848 Variable* var, LookupResult* lookup, bool is_store) { |
2838 bool is_store) { | 2849 if (var->is_this() || !info()->has_global_object()) { |
2839 if (var->is_this()) { | 2850 return kUseGeneric; |
2840 BAILOUT("global this reference"); | |
2841 } | |
2842 if (!info()->has_global_object()) { | |
2843 BAILOUT("no global object to optimize VariableProxy"); | |
2844 } | 2851 } |
2845 Handle<GlobalObject> global(info()->global_object()); | 2852 Handle<GlobalObject> global(info()->global_object()); |
2846 global->Lookup(*var->name(), lookup); | 2853 global->Lookup(*var->name(), lookup); |
2847 if (!lookup->IsProperty()) { | 2854 if (!lookup->IsProperty() || |
2848 BAILOUT("global variable cell not yet introduced"); | 2855 lookup->type() != NORMAL || |
| 2856 (is_store && lookup->IsReadOnly()) || |
| 2857 lookup->holder() != *global) { |
| 2858 return kUseGeneric; |
2849 } | 2859 } |
2850 if (lookup->type() != NORMAL) { | 2860 |
2851 BAILOUT("global variable has accessors"); | 2861 return kUseCell; |
2852 } | |
2853 if (is_store && lookup->IsReadOnly()) { | |
2854 BAILOUT("read-only global variable"); | |
2855 } | |
2856 if (lookup->holder() != *global) { | |
2857 BAILOUT("global property on prototype of global object"); | |
2858 } | |
2859 } | 2862 } |
2860 | 2863 |
2861 | 2864 |
2862 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { | 2865 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
2863 ASSERT(var->IsContextSlot()); | 2866 ASSERT(var->IsContextSlot()); |
2864 HInstruction* context = new HContext; | 2867 HInstruction* context = new HContext; |
2865 AddInstruction(context); | 2868 AddInstruction(context); |
2866 int length = info()->scope()->ContextChainLength(var->scope()); | 2869 int length = info()->scope()->ContextChainLength(var->scope()); |
2867 while (length-- > 0) { | 2870 while (length-- > 0) { |
2868 context = new HOuterContext(context); | 2871 context = new HOuterContext(context); |
(...skipping 15 matching lines...) Expand all Loading... |
2884 } else if (variable->IsContextSlot()) { | 2887 } else if (variable->IsContextSlot()) { |
2885 if (variable->mode() == Variable::CONST) { | 2888 if (variable->mode() == Variable::CONST) { |
2886 BAILOUT("reference to const context slot"); | 2889 BAILOUT("reference to const context slot"); |
2887 } | 2890 } |
2888 HValue* context = BuildContextChainWalk(variable); | 2891 HValue* context = BuildContextChainWalk(variable); |
2889 int index = variable->AsSlot()->index(); | 2892 int index = variable->AsSlot()->index(); |
2890 HLoadContextSlot* instr = new HLoadContextSlot(context, index); | 2893 HLoadContextSlot* instr = new HLoadContextSlot(context, index); |
2891 ast_context()->ReturnInstruction(instr, expr->id()); | 2894 ast_context()->ReturnInstruction(instr, expr->id()); |
2892 } else if (variable->is_global()) { | 2895 } else if (variable->is_global()) { |
2893 LookupResult lookup; | 2896 LookupResult lookup; |
2894 LookupGlobalPropertyCell(variable, &lookup, false); | 2897 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); |
2895 CHECK_BAILOUT; | |
2896 | 2898 |
2897 Handle<GlobalObject> global(info()->global_object()); | 2899 if (type == kUseCell && |
2898 // TODO(3039103): Handle global property load through an IC call when access | 2900 info()->global_object()->IsAccessCheckNeeded()) { |
2899 // checks are enabled. | 2901 type = kUseGeneric; |
2900 if (global->IsAccessCheckNeeded()) { | |
2901 BAILOUT("global object requires access check"); | |
2902 } | 2902 } |
2903 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 2903 |
2904 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 2904 if (type == kUseCell) { |
2905 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); | 2905 Handle<GlobalObject> global(info()->global_object()); |
2906 ast_context()->ReturnInstruction(instr, expr->id()); | 2906 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 2907 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| 2908 HLoadGlobalCell* instr = new HLoadGlobalCell(cell, check_hole); |
| 2909 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2910 } else { |
| 2911 HContext* context = new HContext; |
| 2912 AddInstruction(context); |
| 2913 HGlobalObject* global_object = new HGlobalObject(context); |
| 2914 AddInstruction(global_object); |
| 2915 HLoadGlobalGeneric* instr = |
| 2916 new HLoadGlobalGeneric(context, |
| 2917 global_object, |
| 2918 variable->name(), |
| 2919 ast_context()->is_for_typeof()); |
| 2920 instr->set_position(expr->position()); |
| 2921 ASSERT(instr->HasSideEffects()); |
| 2922 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2923 } |
2907 } else { | 2924 } else { |
2908 BAILOUT("reference to a variable which requires dynamic lookup"); | 2925 BAILOUT("reference to a variable which requires dynamic lookup"); |
2909 } | 2926 } |
2910 } | 2927 } |
2911 | 2928 |
2912 | 2929 |
2913 void HGraphBuilder::VisitLiteral(Literal* expr) { | 2930 void HGraphBuilder::VisitLiteral(Literal* expr) { |
2914 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); | 2931 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); |
2915 ast_context()->ReturnInstruction(instr, expr->id()); | 2932 ast_context()->ReturnInstruction(instr, expr->id()); |
2916 } | 2933 } |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3267 | 3284 |
3268 | 3285 |
3269 // Because not every expression has a position and there is not common | 3286 // Because not every expression has a position and there is not common |
3270 // superclass of Assignment and CountOperation, we cannot just pass the | 3287 // superclass of Assignment and CountOperation, we cannot just pass the |
3271 // owning expression instead of position and ast_id separately. | 3288 // owning expression instead of position and ast_id separately. |
3272 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 3289 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
3273 HValue* value, | 3290 HValue* value, |
3274 int position, | 3291 int position, |
3275 int ast_id) { | 3292 int ast_id) { |
3276 LookupResult lookup; | 3293 LookupResult lookup; |
3277 LookupGlobalPropertyCell(var, &lookup, true); | 3294 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
3278 CHECK_BAILOUT; | 3295 if (type == kUseCell) { |
3279 | 3296 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
3280 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 3297 Handle<GlobalObject> global(info()->global_object()); |
3281 Handle<GlobalObject> global(info()->global_object()); | 3298 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
3282 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3299 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); |
3283 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); | 3300 instr->set_position(position); |
3284 instr->set_position(position); | 3301 AddInstruction(instr); |
3285 AddInstruction(instr); | 3302 if (instr->HasSideEffects()) AddSimulate(ast_id); |
3286 if (instr->HasSideEffects()) AddSimulate(ast_id); | 3303 } else { |
| 3304 BAILOUT("global store only supported for cells"); |
| 3305 } |
3287 } | 3306 } |
3288 | 3307 |
3289 | 3308 |
3290 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 3309 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
3291 Expression* target = expr->target(); | 3310 Expression* target = expr->target(); |
3292 VariableProxy* proxy = target->AsVariableProxy(); | 3311 VariableProxy* proxy = target->AsVariableProxy(); |
3293 Variable* var = proxy->AsVariable(); | 3312 Variable* var = proxy->AsVariable(); |
3294 Property* prop = target->AsProperty(); | 3313 Property* prop = target->AsProperty(); |
3295 ASSERT(var == NULL || prop == NULL); | 3314 ASSERT(var == NULL || prop == NULL); |
3296 | 3315 |
(...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4304 if (!global_call) { | 4323 if (!global_call) { |
4305 ++argument_count; | 4324 ++argument_count; |
4306 VISIT_FOR_VALUE(expr->expression()); | 4325 VISIT_FOR_VALUE(expr->expression()); |
4307 } | 4326 } |
4308 | 4327 |
4309 if (global_call) { | 4328 if (global_call) { |
4310 bool known_global_function = false; | 4329 bool known_global_function = false; |
4311 // If there is a global property cell for the name at compile time and | 4330 // If there is a global property cell for the name at compile time and |
4312 // access check is not enabled we assume that the function will not change | 4331 // access check is not enabled we assume that the function will not change |
4313 // and generate optimized code for calling the function. | 4332 // and generate optimized code for calling the function. |
4314 if (info()->has_global_object() && | 4333 LookupResult lookup; |
| 4334 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| 4335 if (type == kUseCell && |
4315 !info()->global_object()->IsAccessCheckNeeded()) { | 4336 !info()->global_object()->IsAccessCheckNeeded()) { |
4316 Handle<GlobalObject> global(info()->global_object()); | 4337 Handle<GlobalObject> global(info()->global_object()); |
4317 known_global_function = expr->ComputeGlobalTarget(global, var->name()); | 4338 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
4318 } | 4339 } |
4319 if (known_global_function) { | 4340 if (known_global_function) { |
4320 // Push the global object instead of the global receiver because | 4341 // Push the global object instead of the global receiver because |
4321 // code generated by the full code generator expects it. | 4342 // code generated by the full code generator expects it. |
4322 HContext* context = new HContext; | 4343 HContext* context = new HContext; |
4323 HGlobalObject* global_object = new HGlobalObject(context); | 4344 HGlobalObject* global_object = new HGlobalObject(context); |
4324 AddInstruction(context); | 4345 AddInstruction(context); |
4325 PushAndAdd(global_object); | 4346 PushAndAdd(global_object); |
4326 VisitExpressions(expr->arguments()); | 4347 VisitExpressions(expr->arguments()); |
4327 CHECK_BAILOUT; | 4348 CHECK_BAILOUT; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4510 HBasicBlock* join = | 4531 HBasicBlock* join = |
4511 CreateJoin(materialize_false, materialize_true, expr->id()); | 4532 CreateJoin(materialize_false, materialize_true, expr->id()); |
4512 set_current_block(join); | 4533 set_current_block(join); |
4513 ast_context()->ReturnValue(Pop()); | 4534 ast_context()->ReturnValue(Pop()); |
4514 } else { | 4535 } else { |
4515 ASSERT(ast_context()->IsEffect()); | 4536 ASSERT(ast_context()->IsEffect()); |
4516 VisitForEffect(expr->expression()); | 4537 VisitForEffect(expr->expression()); |
4517 } | 4538 } |
4518 | 4539 |
4519 } else if (op == Token::TYPEOF) { | 4540 } else if (op == Token::TYPEOF) { |
4520 VISIT_FOR_VALUE(expr->expression()); | 4541 VisitForTypeOf(expr->expression()); |
| 4542 if (HasStackOverflow()) return; |
4521 HValue* value = Pop(); | 4543 HValue* value = Pop(); |
4522 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); | 4544 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); |
4523 | 4545 |
4524 } else { | 4546 } else { |
4525 VISIT_FOR_VALUE(expr->expression()); | 4547 VISIT_FOR_VALUE(expr->expression()); |
4526 HValue* value = Pop(); | 4548 HValue* value = Pop(); |
4527 HInstruction* instr = NULL; | 4549 HInstruction* instr = NULL; |
4528 switch (op) { | 4550 switch (op) { |
4529 case Token::BIT_NOT: | 4551 case Token::BIT_NOT: |
4530 instr = new HBitNot(value); | 4552 instr = new HBitNot(value); |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4913 ast_context()->ReturnInstruction(instr, expr->id()); | 4935 ast_context()->ReturnInstruction(instr, expr->id()); |
4914 return; | 4936 return; |
4915 } | 4937 } |
4916 | 4938 |
4917 // Check for the pattern: typeof <expression> == <string literal>. | 4939 // Check for the pattern: typeof <expression> == <string literal>. |
4918 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); | 4940 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); |
4919 Literal* right_literal = expr->right()->AsLiteral(); | 4941 Literal* right_literal = expr->right()->AsLiteral(); |
4920 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && | 4942 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
4921 left_unary != NULL && left_unary->op() == Token::TYPEOF && | 4943 left_unary != NULL && left_unary->op() == Token::TYPEOF && |
4922 right_literal != NULL && right_literal->handle()->IsString()) { | 4944 right_literal != NULL && right_literal->handle()->IsString()) { |
4923 VISIT_FOR_VALUE(left_unary->expression()); | 4945 VisitForTypeOf(left_unary->expression()); |
| 4946 if (HasStackOverflow()) return; |
4924 HValue* left = Pop(); | 4947 HValue* left = Pop(); |
4925 HInstruction* instr = new HTypeofIs(left, | 4948 HInstruction* instr = new HTypeofIs(left, |
4926 Handle<String>::cast(right_literal->handle())); | 4949 Handle<String>::cast(right_literal->handle())); |
4927 instr->set_position(expr->position()); | 4950 instr->set_position(expr->position()); |
4928 ast_context()->ReturnInstruction(instr, expr->id()); | 4951 ast_context()->ReturnInstruction(instr, expr->id()); |
4929 return; | 4952 return; |
4930 } | 4953 } |
4931 | 4954 |
4932 VISIT_FOR_VALUE(expr->left()); | 4955 VISIT_FOR_VALUE(expr->left()); |
4933 VISIT_FOR_VALUE(expr->right()); | 4956 VISIT_FOR_VALUE(expr->right()); |
(...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5915 } | 5938 } |
5916 } | 5939 } |
5917 | 5940 |
5918 #ifdef DEBUG | 5941 #ifdef DEBUG |
5919 if (graph_ != NULL) graph_->Verify(); | 5942 if (graph_ != NULL) graph_->Verify(); |
5920 if (allocator_ != NULL) allocator_->Verify(); | 5943 if (allocator_ != NULL) allocator_->Verify(); |
5921 #endif | 5944 #endif |
5922 } | 5945 } |
5923 | 5946 |
5924 } } // namespace v8::internal | 5947 } } // namespace v8::internal |
OLD | NEW |