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 1268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 } | 1279 } |
1280 | 1280 |
1281 | 1281 |
1282 // Simple sparse set with O(1) add, contains, and clear. | 1282 // Simple sparse set with O(1) add, contains, and clear. |
1283 class SparseSet { | 1283 class SparseSet { |
1284 public: | 1284 public: |
1285 SparseSet(Zone* zone, int capacity) | 1285 SparseSet(Zone* zone, int capacity) |
1286 : capacity_(capacity), | 1286 : capacity_(capacity), |
1287 length_(0), | 1287 length_(0), |
1288 dense_(zone->NewArray<int>(capacity)), | 1288 dense_(zone->NewArray<int>(capacity)), |
1289 sparse_(zone->NewArray<int>(capacity)) { | 1289 sparse_(zone->NewArray<int>(capacity)) {} |
1290 #ifndef NVALGRIND | |
1291 // Initialize the sparse array to make valgrind happy. | |
1292 memset(sparse_, 0, sizeof(sparse_[0]) * capacity); | |
1293 #endif | |
1294 } | |
1295 | 1290 |
1296 bool Contains(int n) const { | 1291 bool Contains(int n) const { |
1297 ASSERT(0 <= n && n < capacity_); | 1292 ASSERT(0 <= n && n < capacity_); |
1298 int d = sparse_[n]; | 1293 int d = sparse_[n]; |
1299 return 0 <= d && d < length_ && dense_[d] == n; | 1294 return 0 <= d && d < length_ && dense_[d] == n; |
1300 } | 1295 } |
1301 | 1296 |
1302 bool Add(int n) { | 1297 bool Add(int n) { |
1303 if (Contains(n)) return false; | 1298 if (Contains(n)) return false; |
1304 dense_[length_] = n; | 1299 dense_[length_] = n; |
(...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2005 function_return_(NULL), | 2000 function_return_(NULL), |
2006 test_context_(NULL), | 2001 test_context_(NULL), |
2007 outer_(owner->function_state()) { | 2002 outer_(owner->function_state()) { |
2008 if (outer_ != NULL) { | 2003 if (outer_ != NULL) { |
2009 // State for an inline function. | 2004 // State for an inline function. |
2010 if (owner->ast_context()->IsTest()) { | 2005 if (owner->ast_context()->IsTest()) { |
2011 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); | 2006 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); |
2012 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); | 2007 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); |
2013 if_true->MarkAsInlineReturnTarget(); | 2008 if_true->MarkAsInlineReturnTarget(); |
2014 if_false->MarkAsInlineReturnTarget(); | 2009 if_false->MarkAsInlineReturnTarget(); |
2015 Expression* cond = TestContext::cast(owner->ast_context())->condition(); | |
2016 // The AstContext constructor pushed on the context stack. This newed | 2010 // The AstContext constructor pushed on the context stack. This newed |
2017 // instance is the reason that AstContext can't be BASE_EMBEDDED. | 2011 // instance is the reason that AstContext can't be BASE_EMBEDDED. |
2018 test_context_ = new TestContext(owner, cond, if_true, if_false); | 2012 test_context_ = new TestContext(owner, if_true, if_false); |
2019 } else { | 2013 } else { |
2020 function_return_ = owner->graph()->CreateBasicBlock(); | 2014 function_return_ = owner->graph()->CreateBasicBlock(); |
2021 function_return()->MarkAsInlineReturnTarget(); | 2015 function_return()->MarkAsInlineReturnTarget(); |
2022 } | 2016 } |
2023 // Set this after possibly allocating a new TestContext above. | 2017 // Set this after possibly allocating a new TestContext above. |
2024 call_context_ = owner->ast_context(); | 2018 call_context_ = owner->ast_context(); |
2025 } | 2019 } |
2026 | 2020 |
2027 // Push on the state stack. | 2021 // Push on the state stack. |
2028 owner->set_function_state(this); | 2022 owner->set_function_state(this); |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2178 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 2172 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
2179 for_value.set_for_typeof(true); | 2173 for_value.set_for_typeof(true); |
2180 Visit(expr); | 2174 Visit(expr); |
2181 } | 2175 } |
2182 | 2176 |
2183 | 2177 |
2184 | 2178 |
2185 void HGraphBuilder::VisitForControl(Expression* expr, | 2179 void HGraphBuilder::VisitForControl(Expression* expr, |
2186 HBasicBlock* true_block, | 2180 HBasicBlock* true_block, |
2187 HBasicBlock* false_block) { | 2181 HBasicBlock* false_block) { |
2188 TestContext for_test(this, expr, true_block, false_block); | 2182 TestContext for_test(this, true_block, false_block); |
2189 Visit(expr); | 2183 Visit(expr); |
2190 } | 2184 } |
2191 | 2185 |
2192 | 2186 |
2193 void HGraphBuilder::VisitArgument(Expression* expr) { | 2187 void HGraphBuilder::VisitArgument(Expression* expr) { |
2194 CHECK_ALIVE(VisitForValue(expr)); | 2188 CHECK_ALIVE(VisitForValue(expr)); |
2195 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); | 2189 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); |
2196 } | 2190 } |
2197 | 2191 |
2198 | 2192 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2379 // Initialize specials and locals to undefined. | 2373 // Initialize specials and locals to undefined. |
2380 for (int i = environment()->parameter_count() + 1; | 2374 for (int i = environment()->parameter_count() + 1; |
2381 i < environment()->length(); | 2375 i < environment()->length(); |
2382 ++i) { | 2376 ++i) { |
2383 environment()->Bind(i, undefined_constant); | 2377 environment()->Bind(i, undefined_constant); |
2384 } | 2378 } |
2385 | 2379 |
2386 // Handle the arguments and arguments shadow variables specially (they do | 2380 // Handle the arguments and arguments shadow variables specially (they do |
2387 // not have declarations). | 2381 // not have declarations). |
2388 if (scope->arguments() != NULL) { | 2382 if (scope->arguments() != NULL) { |
2389 if (!scope->arguments()->IsStackAllocated() || | 2383 if (!scope->arguments()->IsStackAllocated()) { |
2390 (scope->arguments_shadow() != NULL && | |
2391 !scope->arguments_shadow()->IsStackAllocated())) { | |
2392 return Bailout("context-allocated arguments"); | 2384 return Bailout("context-allocated arguments"); |
2393 } | 2385 } |
2394 HArgumentsObject* object = new(zone()) HArgumentsObject; | 2386 HArgumentsObject* object = new(zone()) HArgumentsObject; |
2395 AddInstruction(object); | 2387 AddInstruction(object); |
2396 graph()->SetArgumentsObject(object); | 2388 graph()->SetArgumentsObject(object); |
2397 environment()->Bind(scope->arguments(), object); | 2389 environment()->Bind(scope->arguments(), object); |
2398 if (scope->arguments_shadow() != NULL) { | |
2399 environment()->Bind(scope->arguments_shadow(), object); | |
2400 } | |
2401 } | 2390 } |
2402 } | 2391 } |
2403 | 2392 |
2404 | 2393 |
2405 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { | 2394 void HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { |
2406 for (int i = 0; i < statements->length(); i++) { | 2395 for (int i = 0; i < statements->length(); i++) { |
2407 CHECK_ALIVE(Visit(statements->at(i))); | 2396 CHECK_ALIVE(Visit(statements->at(i))); |
2408 } | 2397 } |
2409 } | 2398 } |
2410 | 2399 |
(...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3513 CHECK_ALIVE(VisitForValue(operation)); | 3502 CHECK_ALIVE(VisitForValue(operation)); |
3514 | 3503 |
3515 if (var->is_global()) { | 3504 if (var->is_global()) { |
3516 HandleGlobalVariableAssignment(var, | 3505 HandleGlobalVariableAssignment(var, |
3517 Top(), | 3506 Top(), |
3518 expr->position(), | 3507 expr->position(), |
3519 expr->AssignmentId()); | 3508 expr->AssignmentId()); |
3520 } else if (var->IsStackAllocated()) { | 3509 } else if (var->IsStackAllocated()) { |
3521 Bind(var, Top()); | 3510 Bind(var, Top()); |
3522 } else if (var->IsContextSlot()) { | 3511 } else if (var->IsContextSlot()) { |
| 3512 // Bail out if we try to mutate a parameter value in a function using |
| 3513 // the arguments object. We do not (yet) correctly handle the |
| 3514 // arguments property of the function. |
| 3515 if (info()->scope()->arguments() != NULL) { |
| 3516 // Parameters will rewrite to context slots. We have no direct way |
| 3517 // to detect that the variable is a parameter. |
| 3518 int count = info()->scope()->num_parameters(); |
| 3519 for (int i = 0; i < count; ++i) { |
| 3520 if (var == info()->scope()->parameter(i)) { |
| 3521 Bailout("assignment to parameter, function uses arguments object"); |
| 3522 } |
| 3523 } |
| 3524 } |
| 3525 |
3523 HValue* context = BuildContextChainWalk(var); | 3526 HValue* context = BuildContextChainWalk(var); |
3524 int index = var->AsSlot()->index(); | 3527 int index = var->AsSlot()->index(); |
3525 HStoreContextSlot* instr = | 3528 HStoreContextSlot* instr = |
3526 new(zone()) HStoreContextSlot(context, index, Top()); | 3529 new(zone()) HStoreContextSlot(context, index, Top()); |
3527 AddInstruction(instr); | 3530 AddInstruction(instr); |
3528 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3531 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3529 } else { | 3532 } else { |
3530 return Bailout("compound assignment to lookup slot"); | 3533 return Bailout("compound assignment to lookup slot"); |
3531 } | 3534 } |
3532 ast_context()->ReturnValue(Pop()); | 3535 ast_context()->ReturnValue(Pop()); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3636 // We do not allow the arguments object to occur in a context where it | 3639 // We do not allow the arguments object to occur in a context where it |
3637 // may escape, but assignments to stack-allocated locals are | 3640 // may escape, but assignments to stack-allocated locals are |
3638 // permitted. | 3641 // permitted. |
3639 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); | 3642 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); |
3640 HValue* value = Pop(); | 3643 HValue* value = Pop(); |
3641 Bind(var, value); | 3644 Bind(var, value); |
3642 ast_context()->ReturnValue(value); | 3645 ast_context()->ReturnValue(value); |
3643 | 3646 |
3644 } else if (var->IsContextSlot()) { | 3647 } else if (var->IsContextSlot()) { |
3645 ASSERT(var->mode() != Variable::CONST); | 3648 ASSERT(var->mode() != Variable::CONST); |
| 3649 // Bail out if we try to mutate a parameter value in a function using |
| 3650 // the arguments object. We do not (yet) correctly handle the |
| 3651 // arguments property of the function. |
| 3652 if (info()->scope()->arguments() != NULL) { |
| 3653 // Parameters will rewrite to context slots. We have no direct way |
| 3654 // to detect that the variable is a parameter. |
| 3655 int count = info()->scope()->num_parameters(); |
| 3656 for (int i = 0; i < count; ++i) { |
| 3657 if (var == info()->scope()->parameter(i)) { |
| 3658 Bailout("assignment to parameter, function uses arguments object"); |
| 3659 } |
| 3660 } |
| 3661 } |
| 3662 |
3646 CHECK_ALIVE(VisitForValue(expr->value())); | 3663 CHECK_ALIVE(VisitForValue(expr->value())); |
3647 HValue* context = BuildContextChainWalk(var); | 3664 HValue* context = BuildContextChainWalk(var); |
3648 int index = var->AsSlot()->index(); | 3665 int index = var->AsSlot()->index(); |
3649 HStoreContextSlot* instr = | 3666 HStoreContextSlot* instr = |
3650 new(zone()) HStoreContextSlot(context, index, Top()); | 3667 new(zone()) HStoreContextSlot(context, index, Top()); |
3651 AddInstruction(instr); | 3668 AddInstruction(instr); |
3652 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3669 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
3653 ast_context()->ReturnValue(Pop()); | 3670 ast_context()->ReturnValue(Pop()); |
3654 | 3671 |
3655 } else if (var->is_global()) { | 3672 } else if (var->is_global()) { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3901 val = floor_val; | 3918 val = floor_val; |
3902 break; | 3919 break; |
3903 } | 3920 } |
3904 case JSObject::EXTERNAL_FLOAT_ELEMENTS: | 3921 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
3905 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: | 3922 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
3906 break; | 3923 break; |
3907 | 3924 |
3908 case JSObject::FAST_ELEMENTS: | 3925 case JSObject::FAST_ELEMENTS: |
3909 case JSObject::FAST_DOUBLE_ELEMENTS: | 3926 case JSObject::FAST_DOUBLE_ELEMENTS: |
3910 case JSObject::DICTIONARY_ELEMENTS: | 3927 case JSObject::DICTIONARY_ELEMENTS: |
| 3928 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS: |
3911 UNREACHABLE(); | 3929 UNREACHABLE(); |
3912 break; | 3930 break; |
3913 } | 3931 } |
3914 return new(zone()) HStoreKeyedSpecializedArrayElement( | 3932 return new(zone()) HStoreKeyedSpecializedArrayElement( |
3915 external_elements, | 3933 external_elements, |
3916 checked_key, | 3934 checked_key, |
3917 val, | 3935 val, |
3918 map->elements_kind()); | 3936 map->elements_kind()); |
3919 } | 3937 } |
3920 | 3938 |
(...skipping 876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4797 var->AsSlot() != NULL && | 4815 var->AsSlot() != NULL && |
4798 var->AsSlot()->type() != Slot::LOOKUP) { | 4816 var->AsSlot()->type() != Slot::LOOKUP) { |
4799 // Result of deleting non-global, non-dynamic variables is false. | 4817 // Result of deleting non-global, non-dynamic variables is false. |
4800 // The subexpression does not have side effects. | 4818 // The subexpression does not have side effects. |
4801 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 4819 ast_context()->ReturnValue(graph()->GetConstantFalse()); |
4802 } else if (prop != NULL) { | 4820 } else if (prop != NULL) { |
4803 if (prop->is_synthetic()) { | 4821 if (prop->is_synthetic()) { |
4804 // Result of deleting parameters is false, even when they rewrite | 4822 // Result of deleting parameters is false, even when they rewrite |
4805 // to accesses on the arguments object. | 4823 // to accesses on the arguments object. |
4806 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 4824 ast_context()->ReturnValue(graph()->GetConstantFalse()); |
4807 } else { | 4825 } else { |
4808 CHECK_ALIVE(VisitForValue(prop->obj())); | 4826 CHECK_ALIVE(VisitForValue(prop->obj())); |
4809 CHECK_ALIVE(VisitForValue(prop->key())); | 4827 CHECK_ALIVE(VisitForValue(prop->key())); |
4810 HValue* key = Pop(); | 4828 HValue* key = Pop(); |
4811 HValue* obj = Pop(); | 4829 HValue* obj = Pop(); |
4812 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); | 4830 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); |
4813 ast_context()->ReturnInstruction(instr, expr->id()); | 4831 ast_context()->ReturnInstruction(instr, expr->id()); |
4814 } | 4832 } |
4815 } else if (var->is_global()) { | 4833 } else if (var->is_global()) { |
4816 Bailout("delete with global variable"); | 4834 Bailout("delete with global variable"); |
4817 } else { | 4835 } else { |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4982 Push(after); | 5000 Push(after); |
4983 | 5001 |
4984 if (var->is_global()) { | 5002 if (var->is_global()) { |
4985 HandleGlobalVariableAssignment(var, | 5003 HandleGlobalVariableAssignment(var, |
4986 after, | 5004 after, |
4987 expr->position(), | 5005 expr->position(), |
4988 expr->AssignmentId()); | 5006 expr->AssignmentId()); |
4989 } else if (var->IsStackAllocated()) { | 5007 } else if (var->IsStackAllocated()) { |
4990 Bind(var, after); | 5008 Bind(var, after); |
4991 } else if (var->IsContextSlot()) { | 5009 } else if (var->IsContextSlot()) { |
| 5010 // Bail out if we try to mutate a parameter value in a function using |
| 5011 // the arguments object. We do not (yet) correctly handle the |
| 5012 // arguments property of the function. |
| 5013 if (info()->scope()->arguments() != NULL) { |
| 5014 // Parameters will rewrite to context slots. We have no direct way |
| 5015 // to detect that the variable is a parameter. |
| 5016 int count = info()->scope()->num_parameters(); |
| 5017 for (int i = 0; i < count; ++i) { |
| 5018 if (var == info()->scope()->parameter(i)) { |
| 5019 Bailout("assignment to parameter, function uses arguments object"); |
| 5020 } |
| 5021 } |
| 5022 } |
| 5023 |
4992 HValue* context = BuildContextChainWalk(var); | 5024 HValue* context = BuildContextChainWalk(var); |
4993 int index = var->AsSlot()->index(); | 5025 int index = var->AsSlot()->index(); |
4994 HStoreContextSlot* instr = | 5026 HStoreContextSlot* instr = |
4995 new(zone()) HStoreContextSlot(context, index, after); | 5027 new(zone()) HStoreContextSlot(context, index, after); |
4996 AddInstruction(instr); | 5028 AddInstruction(instr); |
4997 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 5029 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
4998 } else { | 5030 } else { |
4999 return Bailout("lookup variable in count operation"); | 5031 return Bailout("lookup variable in count operation"); |
5000 } | 5032 } |
5001 | 5033 |
(...skipping 1405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6407 } | 6439 } |
6408 } | 6440 } |
6409 | 6441 |
6410 #ifdef DEBUG | 6442 #ifdef DEBUG |
6411 if (graph_ != NULL) graph_->Verify(); | 6443 if (graph_ != NULL) graph_->Verify(); |
6412 if (allocator_ != NULL) allocator_->Verify(); | 6444 if (allocator_ != NULL) allocator_->Verify(); |
6413 #endif | 6445 #endif |
6414 } | 6446 } |
6415 | 6447 |
6416 } } // namespace v8::internal | 6448 } } // namespace v8::internal |
OLD | NEW |