OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 10825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10836 }; | 10836 }; |
10837 | 10837 |
10838 ScopeIterator(Isolate* isolate, | 10838 ScopeIterator(Isolate* isolate, |
10839 JavaScriptFrame* frame, | 10839 JavaScriptFrame* frame, |
10840 int inlined_jsframe_index) | 10840 int inlined_jsframe_index) |
10841 : isolate_(isolate), | 10841 : isolate_(isolate), |
10842 frame_(frame), | 10842 frame_(frame), |
10843 inlined_jsframe_index_(inlined_jsframe_index), | 10843 inlined_jsframe_index_(inlined_jsframe_index), |
10844 function_(JSFunction::cast(frame->function())), | 10844 function_(JSFunction::cast(frame->function())), |
10845 context_(Context::cast(frame->context())), | 10845 context_(Context::cast(frame->context())), |
10846 nested_scope_chain_(4) { | 10846 nested_scope_chain_(4), |
| 10847 failed_(false) { |
10847 | 10848 |
10848 // Catch the case when the debugger stops in an internal function. | 10849 // Catch the case when the debugger stops in an internal function. |
10849 Handle<SharedFunctionInfo> shared_info(function_->shared()); | 10850 Handle<SharedFunctionInfo> shared_info(function_->shared()); |
10850 Handle<ScopeInfo> scope_info(shared_info->scope_info()); | 10851 Handle<ScopeInfo> scope_info(shared_info->scope_info()); |
10851 if (shared_info->script() == isolate->heap()->undefined_value()) { | 10852 if (shared_info->script() == isolate->heap()->undefined_value()) { |
10852 while (context_->closure() == *function_) { | 10853 while (context_->closure() == *function_) { |
10853 context_ = Handle<Context>(context_->previous(), isolate_); | 10854 context_ = Handle<Context>(context_->previous(), isolate_); |
10854 } | 10855 } |
10855 return; | 10856 return; |
10856 } | 10857 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10910 } | 10911 } |
10911 } | 10912 } |
10912 } | 10913 } |
10913 | 10914 |
10914 ScopeIterator(Isolate* isolate, | 10915 ScopeIterator(Isolate* isolate, |
10915 Handle<JSFunction> function) | 10916 Handle<JSFunction> function) |
10916 : isolate_(isolate), | 10917 : isolate_(isolate), |
10917 frame_(NULL), | 10918 frame_(NULL), |
10918 inlined_jsframe_index_(0), | 10919 inlined_jsframe_index_(0), |
10919 function_(function), | 10920 function_(function), |
10920 context_(function->context()) { | 10921 context_(function->context()), |
| 10922 failed_(false) { |
10921 if (function->IsBuiltin()) { | 10923 if (function->IsBuiltin()) { |
10922 context_ = Handle<Context>(); | 10924 context_ = Handle<Context>(); |
10923 } | 10925 } |
10924 } | 10926 } |
10925 | 10927 |
10926 // More scopes? | 10928 // More scopes? |
10927 bool Done() { return context_.is_null(); } | 10929 bool Done() { |
| 10930 ASSERT(!failed_); |
| 10931 return context_.is_null(); |
| 10932 } |
| 10933 |
| 10934 bool Failed() { return failed_; } |
10928 | 10935 |
10929 // Move to the next scope. | 10936 // Move to the next scope. |
10930 void Next() { | 10937 void Next() { |
| 10938 ASSERT(!failed_); |
10931 ScopeType scope_type = Type(); | 10939 ScopeType scope_type = Type(); |
10932 if (scope_type == ScopeTypeGlobal) { | 10940 if (scope_type == ScopeTypeGlobal) { |
10933 // The global scope is always the last in the chain. | 10941 // The global scope is always the last in the chain. |
10934 ASSERT(context_->IsNativeContext()); | 10942 ASSERT(context_->IsNativeContext()); |
10935 context_ = Handle<Context>(); | 10943 context_ = Handle<Context>(); |
10936 return; | 10944 return; |
10937 } | 10945 } |
10938 if (nested_scope_chain_.is_empty()) { | 10946 if (nested_scope_chain_.is_empty()) { |
10939 context_ = Handle<Context>(context_->previous(), isolate_); | 10947 context_ = Handle<Context>(context_->previous(), isolate_); |
10940 } else { | 10948 } else { |
10941 if (nested_scope_chain_.last()->HasContext()) { | 10949 if (nested_scope_chain_.last()->HasContext()) { |
10942 ASSERT(context_->previous() != NULL); | 10950 ASSERT(context_->previous() != NULL); |
10943 context_ = Handle<Context>(context_->previous(), isolate_); | 10951 context_ = Handle<Context>(context_->previous(), isolate_); |
10944 } | 10952 } |
10945 nested_scope_chain_.RemoveLast(); | 10953 nested_scope_chain_.RemoveLast(); |
10946 } | 10954 } |
10947 } | 10955 } |
10948 | 10956 |
10949 // Return the type of the current scope. | 10957 // Return the type of the current scope. |
10950 ScopeType Type() { | 10958 ScopeType Type() { |
| 10959 ASSERT(!failed_); |
10951 if (!nested_scope_chain_.is_empty()) { | 10960 if (!nested_scope_chain_.is_empty()) { |
10952 Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); | 10961 Handle<ScopeInfo> scope_info = nested_scope_chain_.last(); |
10953 switch (scope_info->Type()) { | 10962 switch (scope_info->Type()) { |
10954 case FUNCTION_SCOPE: | 10963 case FUNCTION_SCOPE: |
10955 ASSERT(context_->IsFunctionContext() || | 10964 ASSERT(context_->IsFunctionContext() || |
10956 !scope_info->HasContext()); | 10965 !scope_info->HasContext()); |
10957 return ScopeTypeLocal; | 10966 return ScopeTypeLocal; |
10958 case MODULE_SCOPE: | 10967 case MODULE_SCOPE: |
10959 ASSERT(context_->IsModuleContext()); | 10968 ASSERT(context_->IsModuleContext()); |
10960 return ScopeTypeModule; | 10969 return ScopeTypeModule; |
(...skipping 29 matching lines...) Expand all Loading... |
10990 } | 10999 } |
10991 if (context_->IsModuleContext()) { | 11000 if (context_->IsModuleContext()) { |
10992 return ScopeTypeModule; | 11001 return ScopeTypeModule; |
10993 } | 11002 } |
10994 ASSERT(context_->IsWithContext()); | 11003 ASSERT(context_->IsWithContext()); |
10995 return ScopeTypeWith; | 11004 return ScopeTypeWith; |
10996 } | 11005 } |
10997 | 11006 |
10998 // Return the JavaScript object with the content of the current scope. | 11007 // Return the JavaScript object with the content of the current scope. |
10999 Handle<JSObject> ScopeObject() { | 11008 Handle<JSObject> ScopeObject() { |
| 11009 ASSERT(!failed_); |
11000 switch (Type()) { | 11010 switch (Type()) { |
11001 case ScopeIterator::ScopeTypeGlobal: | 11011 case ScopeIterator::ScopeTypeGlobal: |
11002 return Handle<JSObject>(CurrentContext()->global_object()); | 11012 return Handle<JSObject>(CurrentContext()->global_object()); |
11003 case ScopeIterator::ScopeTypeLocal: | 11013 case ScopeIterator::ScopeTypeLocal: |
11004 // Materialize the content of the local scope into a JSObject. | 11014 // Materialize the content of the local scope into a JSObject. |
11005 ASSERT(nested_scope_chain_.length() == 1); | 11015 ASSERT(nested_scope_chain_.length() == 1); |
11006 return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_); | 11016 return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_); |
11007 case ScopeIterator::ScopeTypeWith: | 11017 case ScopeIterator::ScopeTypeWith: |
11008 // Return the with object. | 11018 // Return the with object. |
11009 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); | 11019 return Handle<JSObject>(JSObject::cast(CurrentContext()->extension())); |
11010 case ScopeIterator::ScopeTypeCatch: | 11020 case ScopeIterator::ScopeTypeCatch: |
11011 return MaterializeCatchScope(isolate_, CurrentContext()); | 11021 return MaterializeCatchScope(isolate_, CurrentContext()); |
11012 case ScopeIterator::ScopeTypeClosure: | 11022 case ScopeIterator::ScopeTypeClosure: |
11013 // Materialize the content of the closure scope into a JSObject. | 11023 // Materialize the content of the closure scope into a JSObject. |
11014 return MaterializeClosure(isolate_, CurrentContext()); | 11024 return MaterializeClosure(isolate_, CurrentContext()); |
11015 case ScopeIterator::ScopeTypeBlock: | 11025 case ScopeIterator::ScopeTypeBlock: |
11016 return MaterializeBlockScope(isolate_, CurrentContext()); | 11026 return MaterializeBlockScope(isolate_, CurrentContext()); |
11017 case ScopeIterator::ScopeTypeModule: | 11027 case ScopeIterator::ScopeTypeModule: |
11018 return MaterializeModuleScope(isolate_, CurrentContext()); | 11028 return MaterializeModuleScope(isolate_, CurrentContext()); |
11019 } | 11029 } |
11020 UNREACHABLE(); | 11030 UNREACHABLE(); |
11021 return Handle<JSObject>(); | 11031 return Handle<JSObject>(); |
11022 } | 11032 } |
11023 | 11033 |
11024 Handle<ScopeInfo> CurrentScopeInfo() { | 11034 Handle<ScopeInfo> CurrentScopeInfo() { |
| 11035 ASSERT(!failed_); |
11025 if (!nested_scope_chain_.is_empty()) { | 11036 if (!nested_scope_chain_.is_empty()) { |
11026 return nested_scope_chain_.last(); | 11037 return nested_scope_chain_.last(); |
11027 } else if (context_->IsBlockContext()) { | 11038 } else if (context_->IsBlockContext()) { |
11028 return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension())); | 11039 return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension())); |
11029 } else if (context_->IsFunctionContext()) { | 11040 } else if (context_->IsFunctionContext()) { |
11030 return Handle<ScopeInfo>(context_->closure()->shared()->scope_info()); | 11041 return Handle<ScopeInfo>(context_->closure()->shared()->scope_info()); |
11031 } | 11042 } |
11032 return Handle<ScopeInfo>::null(); | 11043 return Handle<ScopeInfo>::null(); |
11033 } | 11044 } |
11034 | 11045 |
11035 // Return the context for this scope. For the local context there might not | 11046 // Return the context for this scope. For the local context there might not |
11036 // be an actual context. | 11047 // be an actual context. |
11037 Handle<Context> CurrentContext() { | 11048 Handle<Context> CurrentContext() { |
| 11049 ASSERT(!failed_); |
11038 if (Type() == ScopeTypeGlobal || | 11050 if (Type() == ScopeTypeGlobal || |
11039 nested_scope_chain_.is_empty()) { | 11051 nested_scope_chain_.is_empty()) { |
11040 return context_; | 11052 return context_; |
11041 } else if (nested_scope_chain_.last()->HasContext()) { | 11053 } else if (nested_scope_chain_.last()->HasContext()) { |
11042 return context_; | 11054 return context_; |
11043 } else { | 11055 } else { |
11044 return Handle<Context>(); | 11056 return Handle<Context>(); |
11045 } | 11057 } |
11046 } | 11058 } |
11047 | 11059 |
11048 #ifdef DEBUG | 11060 #ifdef DEBUG |
11049 // Debug print of the content of the current scope. | 11061 // Debug print of the content of the current scope. |
11050 void DebugPrint() { | 11062 void DebugPrint() { |
| 11063 ASSERT(!failed_); |
11051 switch (Type()) { | 11064 switch (Type()) { |
11052 case ScopeIterator::ScopeTypeGlobal: | 11065 case ScopeIterator::ScopeTypeGlobal: |
11053 PrintF("Global:\n"); | 11066 PrintF("Global:\n"); |
11054 CurrentContext()->Print(); | 11067 CurrentContext()->Print(); |
11055 break; | 11068 break; |
11056 | 11069 |
11057 case ScopeIterator::ScopeTypeLocal: { | 11070 case ScopeIterator::ScopeTypeLocal: { |
11058 PrintF("Local:\n"); | 11071 PrintF("Local:\n"); |
11059 function_->shared()->scope_info()->Print(); | 11072 function_->shared()->scope_info()->Print(); |
11060 if (!CurrentContext().is_null()) { | 11073 if (!CurrentContext().is_null()) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11098 } | 11111 } |
11099 #endif | 11112 #endif |
11100 | 11113 |
11101 private: | 11114 private: |
11102 Isolate* isolate_; | 11115 Isolate* isolate_; |
11103 JavaScriptFrame* frame_; | 11116 JavaScriptFrame* frame_; |
11104 int inlined_jsframe_index_; | 11117 int inlined_jsframe_index_; |
11105 Handle<JSFunction> function_; | 11118 Handle<JSFunction> function_; |
11106 Handle<Context> context_; | 11119 Handle<Context> context_; |
11107 List<Handle<ScopeInfo> > nested_scope_chain_; | 11120 List<Handle<ScopeInfo> > nested_scope_chain_; |
| 11121 bool failed_; |
11108 | 11122 |
11109 void RetrieveScopeChain(Scope* scope, | 11123 void RetrieveScopeChain(Scope* scope, |
11110 Handle<SharedFunctionInfo> shared_info) { | 11124 Handle<SharedFunctionInfo> shared_info) { |
11111 if (scope != NULL) { | 11125 if (scope != NULL) { |
11112 int source_position = shared_info->code()->SourcePosition(frame_->pc()); | 11126 int source_position = shared_info->code()->SourcePosition(frame_->pc()); |
11113 scope->GetNestedScopeChain(&nested_scope_chain_, source_position); | 11127 scope->GetNestedScopeChain(&nested_scope_chain_, source_position); |
11114 } else { | 11128 } else { |
11115 // A failed reparse indicates that the preparser has diverged from the | 11129 // A failed reparse indicates that the preparser has diverged from the |
11116 // parser or that the preparse data given to the initial parse has been | 11130 // parser or that the preparse data given to the initial parse has been |
11117 // faulty. We fail in debug mode but in release mode we only provide the | 11131 // faulty. We fail in debug mode but in release mode we only provide the |
11118 // information we get from the context chain but nothing about | 11132 // information we get from the context chain but nothing about |
11119 // completely stack allocated scopes or stack allocated locals. | 11133 // completely stack allocated scopes or stack allocated locals. |
11120 UNREACHABLE(); | 11134 // Or it could be due to stack overflow. |
| 11135 ASSERT(isolate_->has_pending_exception()); |
| 11136 failed_ = true; |
11121 } | 11137 } |
11122 } | 11138 } |
11123 | 11139 |
11124 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); | 11140 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator); |
11125 }; | 11141 }; |
11126 | 11142 |
11127 | 11143 |
11128 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) { | 11144 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) { |
11129 HandleScope scope(isolate); | 11145 HandleScope scope(isolate); |
11130 ASSERT(args.length() == 2); | 11146 ASSERT(args.length() == 2); |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11535 static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate, | 11551 static Handle<Context> CopyNestedScopeContextChain(Isolate* isolate, |
11536 Handle<JSFunction> function, | 11552 Handle<JSFunction> function, |
11537 Handle<Context> base, | 11553 Handle<Context> base, |
11538 JavaScriptFrame* frame, | 11554 JavaScriptFrame* frame, |
11539 int inlined_jsframe_index) { | 11555 int inlined_jsframe_index) { |
11540 HandleScope scope(isolate); | 11556 HandleScope scope(isolate); |
11541 List<Handle<ScopeInfo> > scope_chain; | 11557 List<Handle<ScopeInfo> > scope_chain; |
11542 List<Handle<Context> > context_chain; | 11558 List<Handle<Context> > context_chain; |
11543 | 11559 |
11544 ScopeIterator it(isolate, frame, inlined_jsframe_index); | 11560 ScopeIterator it(isolate, frame, inlined_jsframe_index); |
| 11561 if (it.Failed()) return Handle<Context>::null(); |
| 11562 |
11545 for (; it.Type() != ScopeIterator::ScopeTypeGlobal && | 11563 for (; it.Type() != ScopeIterator::ScopeTypeGlobal && |
11546 it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) { | 11564 it.Type() != ScopeIterator::ScopeTypeLocal ; it.Next()) { |
11547 ASSERT(!it.Done()); | 11565 ASSERT(!it.Done()); |
11548 scope_chain.Add(it.CurrentScopeInfo()); | 11566 scope_chain.Add(it.CurrentScopeInfo()); |
11549 context_chain.Add(it.CurrentContext()); | 11567 context_chain.Add(it.CurrentContext()); |
11550 } | 11568 } |
11551 | 11569 |
11552 // At the end of the chain. Return the base context to link to. | 11570 // At the end of the chain. Return the base context to link to. |
11553 Handle<Context> context = base; | 11571 Handle<Context> context = base; |
11554 | 11572 |
11555 // Iteratively copy and or materialize the nested contexts. | 11573 // Iteratively copy and or materialize the nested contexts. |
11556 while (!scope_chain.is_empty()) { | 11574 while (!scope_chain.is_empty()) { |
11557 Handle<ScopeInfo> scope_info = scope_chain.RemoveLast(); | 11575 Handle<ScopeInfo> scope_info = scope_chain.RemoveLast(); |
11558 Handle<Context> current = context_chain.RemoveLast(); | 11576 Handle<Context> current = context_chain.RemoveLast(); |
11559 ASSERT(!(scope_info->HasContext() & current.is_null())); | 11577 ASSERT(!(scope_info->HasContext() & current.is_null())); |
11560 | 11578 |
11561 if (scope_info->Type() == CATCH_SCOPE) { | 11579 if (scope_info->Type() == CATCH_SCOPE) { |
11562 Handle<String> name(String::cast(current->extension())); | 11580 Handle<String> name(String::cast(current->extension())); |
11563 Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX)); | 11581 Handle<Object> thrown_object(current->get(Context::THROWN_OBJECT_INDEX)); |
11564 context = | 11582 context = |
11565 isolate->factory()->NewCatchContext(function, | 11583 isolate->factory()->NewCatchContext(function, |
11566 context, | 11584 context, |
11567 name, | 11585 name, |
11568 thrown_object); | 11586 thrown_object); |
11569 } else if (scope_info->Type() == BLOCK_SCOPE) { | 11587 } else if (scope_info->Type() == BLOCK_SCOPE) { |
11570 // Materialize the contents of the block scope into a JSObject. | 11588 // Materialize the contents of the block scope into a JSObject. |
11571 Handle<JSObject> block_scope_object = | 11589 Handle<JSObject> block_scope_object = |
11572 MaterializeBlockScope(isolate, current); | 11590 MaterializeBlockScope(isolate, current); |
11573 if (block_scope_object.is_null()) { | 11591 CHECK(!block_scope_object.is_null()); |
11574 return Handle<Context>::null(); | |
11575 } | |
11576 // Allocate a new function context for the debug evaluation and set the | 11592 // Allocate a new function context for the debug evaluation and set the |
11577 // extension object. | 11593 // extension object. |
11578 Handle<Context> new_context = | 11594 Handle<Context> new_context = |
11579 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, | 11595 isolate->factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, |
11580 function); | 11596 function); |
11581 new_context->set_extension(*block_scope_object); | 11597 new_context->set_extension(*block_scope_object); |
11582 new_context->set_previous(*context); | 11598 new_context->set_previous(*context); |
11583 context = new_context; | 11599 context = new_context; |
11584 } else { | 11600 } else { |
11585 ASSERT(scope_info->Type() == WITH_SCOPE); | 11601 ASSERT(scope_info->Type() == WITH_SCOPE); |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11726 Handle<Context> function_context; | 11742 Handle<Context> function_context; |
11727 // Get the function's context if it has one. | 11743 // Get the function's context if it has one. |
11728 if (scope_info->HasContext()) { | 11744 if (scope_info->HasContext()) { |
11729 function_context = Handle<Context>(frame_context->declaration_context()); | 11745 function_context = Handle<Context>(frame_context->declaration_context()); |
11730 } | 11746 } |
11731 context = CopyNestedScopeContextChain(isolate, | 11747 context = CopyNestedScopeContextChain(isolate, |
11732 go_between, | 11748 go_between, |
11733 context, | 11749 context, |
11734 frame, | 11750 frame, |
11735 inlined_jsframe_index); | 11751 inlined_jsframe_index); |
| 11752 if (context.is_null()) { |
| 11753 ASSERT(isolate->has_pending_exception()); |
| 11754 MaybeObject* exception = isolate->pending_exception(); |
| 11755 isolate->clear_pending_exception(); |
| 11756 return exception; |
| 11757 } |
11736 | 11758 |
11737 if (additional_context->IsJSObject()) { | 11759 if (additional_context->IsJSObject()) { |
11738 Handle<JSObject> extension = Handle<JSObject>::cast(additional_context); | 11760 Handle<JSObject> extension = Handle<JSObject>::cast(additional_context); |
11739 context = | 11761 context = |
11740 isolate->factory()->NewWithContext(go_between, context, extension); | 11762 isolate->factory()->NewWithContext(go_between, context, extension); |
11741 } | 11763 } |
11742 | 11764 |
11743 // Wrap the evaluation statement in a new function compiled in the newly | 11765 // Wrap the evaluation statement in a new function compiled in the newly |
11744 // created context. The function has one parameter which has to be called | 11766 // created context. The function has one parameter which has to be called |
11745 // 'arguments'. This it to have access to what would have been 'arguments' in | 11767 // 'arguments'. This it to have access to what would have been 'arguments' in |
(...skipping 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13262 // Handle last resort GC and make sure to allow future allocations | 13284 // Handle last resort GC and make sure to allow future allocations |
13263 // to grow the heap without causing GCs (if possible). | 13285 // to grow the heap without causing GCs (if possible). |
13264 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13286 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13265 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13287 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
13266 "Runtime::PerformGC"); | 13288 "Runtime::PerformGC"); |
13267 } | 13289 } |
13268 } | 13290 } |
13269 | 13291 |
13270 | 13292 |
13271 } } // namespace v8::internal | 13293 } } // namespace v8::internal |
OLD | NEW |