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