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