| 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 |