| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/interpreter/interpreter-assembler.h" | 5 #include "src/interpreter/interpreter-assembler.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <ostream> | 8 #include <ostream> |
| 9 | 9 |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 | 90 |
| 91 Variable cur_depth(this, MachineRepresentation::kWord32); | 91 Variable cur_depth(this, MachineRepresentation::kWord32); |
| 92 cur_depth.Bind(depth); | 92 cur_depth.Bind(depth); |
| 93 | 93 |
| 94 Label context_found(this); | 94 Label context_found(this); |
| 95 | 95 |
| 96 Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context}; | 96 Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context}; |
| 97 Label context_search(this, 2, context_search_loop_variables); | 97 Label context_search(this, 2, context_search_loop_variables); |
| 98 | 98 |
| 99 // Fast path if the depth is 0. | 99 // Fast path if the depth is 0. |
| 100 BranchIfWord32Equal(depth, Int32Constant(0), &context_found, &context_search); | 100 Branch(Word32Equal(depth, Int32Constant(0)), &context_found, &context_search); |
| 101 | 101 |
| 102 // Loop until the depth is 0. | 102 // Loop until the depth is 0. |
| 103 Bind(&context_search); | 103 Bind(&context_search); |
| 104 { | 104 { |
| 105 cur_depth.Bind(Int32Sub(cur_depth.value(), Int32Constant(1))); | 105 cur_depth.Bind(Int32Sub(cur_depth.value(), Int32Constant(1))); |
| 106 cur_context.Bind( | 106 cur_context.Bind( |
| 107 LoadContextSlot(cur_context.value(), Context::PREVIOUS_INDEX)); | 107 LoadContextSlot(cur_context.value(), Context::PREVIOUS_INDEX)); |
| 108 | 108 |
| 109 BranchIfWord32Equal(cur_depth.value(), Int32Constant(0), &context_found, | 109 Branch(Word32Equal(cur_depth.value(), Int32Constant(0)), &context_found, |
| 110 &context_search); | 110 &context_search); |
| 111 } | 111 } |
| 112 | 112 |
| 113 Bind(&context_found); | 113 Bind(&context_found); |
| 114 return cur_context.value(); | 114 return cur_context.value(); |
| 115 } | 115 } |
| 116 | 116 |
| 117 void InterpreterAssembler::GotoIfHasContextExtensionUpToDepth(Node* context, | 117 void InterpreterAssembler::GotoIfHasContextExtensionUpToDepth(Node* context, |
| 118 Node* depth, | 118 Node* depth, |
| 119 Label* target) { | 119 Label* target) { |
| 120 Variable cur_context(this, MachineRepresentation::kTaggedPointer); | 120 Variable cur_context(this, MachineRepresentation::kTaggedPointer); |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 // Slot id of 0 is used to indicate no typefeedback is available. Call using | 572 // Slot id of 0 is used to indicate no typefeedback is available. Call using |
| 573 // call builtin. | 573 // call builtin. |
| 574 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); | 574 STATIC_ASSERT(TypeFeedbackVector::kReservedIndexCount > 0); |
| 575 Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0)); | 575 Node* is_feedback_unavailable = Word32Equal(slot_id, Int32Constant(0)); |
| 576 GotoIf(is_feedback_unavailable, &call_without_feedback); | 576 GotoIf(is_feedback_unavailable, &call_without_feedback); |
| 577 | 577 |
| 578 // The checks. First, does function match the recorded monomorphic target? | 578 // The checks. First, does function match the recorded monomorphic target? |
| 579 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); | 579 Node* feedback_element = LoadFixedArrayElement(type_feedback_vector, slot_id); |
| 580 Node* feedback_value = LoadWeakCellValue(feedback_element); | 580 Node* feedback_value = LoadWeakCellValue(feedback_element); |
| 581 Node* is_monomorphic = WordEqual(function, feedback_value); | 581 Node* is_monomorphic = WordEqual(function, feedback_value); |
| 582 BranchIf(is_monomorphic, &handle_monomorphic, &extra_checks); | 582 Branch(is_monomorphic, &handle_monomorphic, &extra_checks); |
| 583 | 583 |
| 584 Bind(&handle_monomorphic); | 584 Bind(&handle_monomorphic); |
| 585 { | 585 { |
| 586 // The compare above could have been a SMI/SMI comparison. Guard against | 586 // The compare above could have been a SMI/SMI comparison. Guard against |
| 587 // this convincing us that we have a monomorphic JSFunction. | 587 // this convincing us that we have a monomorphic JSFunction. |
| 588 Node* is_smi = TaggedIsSmi(function); | 588 Node* is_smi = TaggedIsSmi(function); |
| 589 GotoIf(is_smi, &extra_checks); | 589 GotoIf(is_smi, &extra_checks); |
| 590 | 590 |
| 591 // Increment the call count. | 591 // Increment the call count. |
| 592 IncrementCallCount(type_feedback_vector, slot_id); | 592 IncrementCallCount(type_feedback_vector, slot_id); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 603 | 603 |
| 604 Bind(&extra_checks); | 604 Bind(&extra_checks); |
| 605 { | 605 { |
| 606 Label check_initialized(this, Label::kDeferred), mark_megamorphic(this), | 606 Label check_initialized(this, Label::kDeferred), mark_megamorphic(this), |
| 607 check_allocation_site(this), | 607 check_allocation_site(this), |
| 608 create_allocation_site(this, Label::kDeferred); | 608 create_allocation_site(this, Label::kDeferred); |
| 609 // Check if it is a megamorphic target | 609 // Check if it is a megamorphic target |
| 610 Node* is_megamorphic = WordEqual( | 610 Node* is_megamorphic = WordEqual( |
| 611 feedback_element, | 611 feedback_element, |
| 612 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | 612 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
| 613 BranchIf(is_megamorphic, &call, &check_allocation_site); | 613 Branch(is_megamorphic, &call, &check_allocation_site); |
| 614 | 614 |
| 615 Bind(&check_allocation_site); | 615 Bind(&check_allocation_site); |
| 616 { | 616 { |
| 617 Node* is_allocation_site = | 617 Node* is_allocation_site = |
| 618 WordEqual(LoadMap(feedback_element), | 618 WordEqual(LoadMap(feedback_element), |
| 619 LoadRoot(Heap::kAllocationSiteMapRootIndex)); | 619 LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
| 620 GotoUnless(is_allocation_site, &check_initialized); | 620 GotoUnless(is_allocation_site, &check_initialized); |
| 621 | 621 |
| 622 // If it is not the Array() function, mark megamorphic. | 622 // If it is not the Array() function, mark megamorphic. |
| 623 Node* context_slot = | 623 Node* context_slot = |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 GotoIf(is_feedback_unavailable, &call_construct); | 774 GotoIf(is_feedback_unavailable, &call_construct); |
| 775 | 775 |
| 776 // Check that the constructor is not a smi. | 776 // Check that the constructor is not a smi. |
| 777 Node* is_smi = TaggedIsSmi(constructor); | 777 Node* is_smi = TaggedIsSmi(constructor); |
| 778 GotoIf(is_smi, &call_construct); | 778 GotoIf(is_smi, &call_construct); |
| 779 | 779 |
| 780 // Check that constructor is a JSFunction. | 780 // Check that constructor is a JSFunction. |
| 781 Node* instance_type = LoadInstanceType(constructor); | 781 Node* instance_type = LoadInstanceType(constructor); |
| 782 Node* is_js_function = | 782 Node* is_js_function = |
| 783 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); | 783 WordEqual(instance_type, Int32Constant(JS_FUNCTION_TYPE)); |
| 784 BranchIf(is_js_function, &js_function, &call_construct); | 784 Branch(is_js_function, &js_function, &call_construct); |
| 785 | 785 |
| 786 Bind(&js_function); | 786 Bind(&js_function); |
| 787 { | 787 { |
| 788 // Cache the called function in a feedback vector slot. Cache states | 788 // Cache the called function in a feedback vector slot. Cache states |
| 789 // are uninitialized, monomorphic (indicated by a JSFunction), and | 789 // are uninitialized, monomorphic (indicated by a JSFunction), and |
| 790 // megamorphic. | 790 // megamorphic. |
| 791 // TODO(mythria/v8:5210): Check if it is better to mark extra_checks as a | 791 // TODO(mythria/v8:5210): Check if it is better to mark extra_checks as a |
| 792 // deferred block so that call_construct_function will be scheduled. | 792 // deferred block so that call_construct_function will be scheduled. |
| 793 Label extra_checks(this), call_construct_function(this); | 793 Label extra_checks(this), call_construct_function(this); |
| 794 | 794 |
| 795 Node* feedback_element = | 795 Node* feedback_element = |
| 796 LoadFixedArrayElement(type_feedback_vector, slot_id); | 796 LoadFixedArrayElement(type_feedback_vector, slot_id); |
| 797 Node* feedback_value = LoadWeakCellValue(feedback_element); | 797 Node* feedback_value = LoadWeakCellValue(feedback_element); |
| 798 Node* is_monomorphic = WordEqual(constructor, feedback_value); | 798 Node* is_monomorphic = WordEqual(constructor, feedback_value); |
| 799 BranchIf(is_monomorphic, &call_construct_function, &extra_checks); | 799 Branch(is_monomorphic, &call_construct_function, &extra_checks); |
| 800 | 800 |
| 801 Bind(&extra_checks); | 801 Bind(&extra_checks); |
| 802 { | 802 { |
| 803 Label mark_megamorphic(this), initialize(this), | 803 Label mark_megamorphic(this), initialize(this), |
| 804 check_allocation_site(this), check_initialized(this), | 804 check_allocation_site(this), check_initialized(this), |
| 805 set_alloc_feedback_and_call(this); | 805 set_alloc_feedback_and_call(this); |
| 806 { | 806 { |
| 807 // Check if it is a megamorphic target | 807 // Check if it is a megamorphic target |
| 808 Comment("check if megamorphic"); | 808 Comment("check if megamorphic"); |
| 809 Node* is_megamorphic = WordEqual( | 809 Node* is_megamorphic = WordEqual( |
| 810 feedback_element, | 810 feedback_element, |
| 811 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); | 811 HeapConstant(TypeFeedbackVector::MegamorphicSentinel(isolate()))); |
| 812 GotoIf(is_megamorphic, &call_construct_function); | 812 GotoIf(is_megamorphic, &call_construct_function); |
| 813 | 813 |
| 814 Comment("check if weak cell"); | 814 Comment("check if weak cell"); |
| 815 Node* is_weak_cell = WordEqual(LoadMap(feedback_element), | 815 Node* is_weak_cell = WordEqual(LoadMap(feedback_element), |
| 816 LoadRoot(Heap::kWeakCellMapRootIndex)); | 816 LoadRoot(Heap::kWeakCellMapRootIndex)); |
| 817 GotoUnless(is_weak_cell, &check_allocation_site); | 817 GotoUnless(is_weak_cell, &check_allocation_site); |
| 818 // If the weak cell is cleared, we have a new chance to become | 818 // If the weak cell is cleared, we have a new chance to become |
| 819 // monomorphic. | 819 // monomorphic. |
| 820 Comment("check if weak cell is cleared"); | 820 Comment("check if weak cell is cleared"); |
| 821 Node* is_smi = TaggedIsSmi(feedback_value); | 821 Node* is_smi = TaggedIsSmi(feedback_value); |
| 822 BranchIf(is_smi, &initialize, &mark_megamorphic); | 822 Branch(is_smi, &initialize, &mark_megamorphic); |
| 823 } | 823 } |
| 824 | 824 |
| 825 Bind(&check_allocation_site); | 825 Bind(&check_allocation_site); |
| 826 { | 826 { |
| 827 Comment("check if it is an allocation site"); | 827 Comment("check if it is an allocation site"); |
| 828 Node* is_allocation_site = | 828 Node* is_allocation_site = |
| 829 WordEqual(LoadObjectField(feedback_element, 0), | 829 WordEqual(LoadObjectField(feedback_element, 0), |
| 830 LoadRoot(Heap::kAllocationSiteMapRootIndex)); | 830 LoadRoot(Heap::kAllocationSiteMapRootIndex)); |
| 831 GotoUnless(is_allocation_site, &check_initialized); | 831 GotoUnless(is_allocation_site, &check_initialized); |
| 832 | 832 |
| 833 // Make sure the function is the Array() function | 833 // Make sure the function is the Array() function |
| 834 Node* context_slot = | 834 Node* context_slot = |
| 835 LoadFixedArrayElement(LoadNativeContext(context), | 835 LoadFixedArrayElement(LoadNativeContext(context), |
| 836 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); | 836 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
| 837 Node* is_array_function = WordEqual(context_slot, constructor); | 837 Node* is_array_function = WordEqual(context_slot, constructor); |
| 838 BranchIf(is_array_function, &set_alloc_feedback_and_call, | 838 Branch(is_array_function, &set_alloc_feedback_and_call, |
| 839 &mark_megamorphic); | 839 &mark_megamorphic); |
| 840 } | 840 } |
| 841 | 841 |
| 842 Bind(&set_alloc_feedback_and_call); | 842 Bind(&set_alloc_feedback_and_call); |
| 843 { | 843 { |
| 844 allocation_feedback.Bind(feedback_element); | 844 allocation_feedback.Bind(feedback_element); |
| 845 Goto(&call_construct_function); | 845 Goto(&call_construct_function); |
| 846 } | 846 } |
| 847 | 847 |
| 848 Bind(&check_initialized); | 848 Bind(&check_initialized); |
| 849 { | 849 { |
| 850 // Check if it is uninitialized. | 850 // Check if it is uninitialized. |
| 851 Comment("check if uninitialized"); | 851 Comment("check if uninitialized"); |
| 852 Node* is_uninitialized = WordEqual( | 852 Node* is_uninitialized = WordEqual( |
| 853 feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex)); | 853 feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex)); |
| 854 BranchIf(is_uninitialized, &initialize, &mark_megamorphic); | 854 Branch(is_uninitialized, &initialize, &mark_megamorphic); |
| 855 } | 855 } |
| 856 | 856 |
| 857 Bind(&initialize); | 857 Bind(&initialize); |
| 858 { | 858 { |
| 859 Label create_weak_cell(this), create_allocation_site(this); | 859 Label create_weak_cell(this), create_allocation_site(this); |
| 860 Comment("initialize the feedback element"); | 860 Comment("initialize the feedback element"); |
| 861 // Check that it is the Array() function. | 861 // Check that it is the Array() function. |
| 862 Node* context_slot = | 862 Node* context_slot = |
| 863 LoadFixedArrayElement(LoadNativeContext(context), | 863 LoadFixedArrayElement(LoadNativeContext(context), |
| 864 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); | 864 Int32Constant(Context::ARRAY_FUNCTION_INDEX)); |
| 865 Node* is_array_function = WordEqual(context_slot, constructor); | 865 Node* is_array_function = WordEqual(context_slot, constructor); |
| 866 BranchIf(is_array_function, &create_allocation_site, &create_weak_cell); | 866 Branch(is_array_function, &create_allocation_site, &create_weak_cell); |
| 867 | 867 |
| 868 Bind(&create_allocation_site); | 868 Bind(&create_allocation_site); |
| 869 { | 869 { |
| 870 Node* site = CreateAllocationSiteInFeedbackVector( | 870 Node* site = CreateAllocationSiteInFeedbackVector( |
| 871 type_feedback_vector, SmiTag(slot_id)); | 871 type_feedback_vector, SmiTag(slot_id)); |
| 872 allocation_feedback.Bind(site); | 872 allocation_feedback.Bind(site); |
| 873 Goto(&call_construct_function); | 873 Goto(&call_construct_function); |
| 874 } | 874 } |
| 875 | 875 |
| 876 Bind(&create_weak_cell); | 876 Bind(&create_weak_cell); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1000 | 1000 |
| 1001 UpdateInterruptBudget(delta); | 1001 UpdateInterruptBudget(delta); |
| 1002 Node* new_bytecode_offset = Advance(delta); | 1002 Node* new_bytecode_offset = Advance(delta); |
| 1003 Node* target_bytecode = LoadBytecode(new_bytecode_offset); | 1003 Node* target_bytecode = LoadBytecode(new_bytecode_offset); |
| 1004 return DispatchToBytecode(target_bytecode, new_bytecode_offset); | 1004 return DispatchToBytecode(target_bytecode, new_bytecode_offset); |
| 1005 } | 1005 } |
| 1006 | 1006 |
| 1007 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) { | 1007 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) { |
| 1008 Label match(this), no_match(this); | 1008 Label match(this), no_match(this); |
| 1009 | 1009 |
| 1010 BranchIf(condition, &match, &no_match); | 1010 Branch(condition, &match, &no_match); |
| 1011 Bind(&match); | 1011 Bind(&match); |
| 1012 Jump(delta); | 1012 Jump(delta); |
| 1013 Bind(&no_match); | 1013 Bind(&no_match); |
| 1014 Dispatch(); | 1014 Dispatch(); |
| 1015 } | 1015 } |
| 1016 | 1016 |
| 1017 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { | 1017 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) { |
| 1018 JumpConditional(WordEqual(lhs, rhs), delta); | 1018 JumpConditional(WordEqual(lhs, rhs), delta); |
| 1019 } | 1019 } |
| 1020 | 1020 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1033 } | 1033 } |
| 1034 | 1034 |
| 1035 Node* InterpreterAssembler::StarDispatchLookahead(Node* target_bytecode) { | 1035 Node* InterpreterAssembler::StarDispatchLookahead(Node* target_bytecode) { |
| 1036 Label do_inline_star(this), done(this); | 1036 Label do_inline_star(this), done(this); |
| 1037 | 1037 |
| 1038 Variable var_bytecode(this, MachineType::PointerRepresentation()); | 1038 Variable var_bytecode(this, MachineType::PointerRepresentation()); |
| 1039 var_bytecode.Bind(target_bytecode); | 1039 var_bytecode.Bind(target_bytecode); |
| 1040 | 1040 |
| 1041 Node* star_bytecode = IntPtrConstant(static_cast<int>(Bytecode::kStar)); | 1041 Node* star_bytecode = IntPtrConstant(static_cast<int>(Bytecode::kStar)); |
| 1042 Node* is_star = WordEqual(target_bytecode, star_bytecode); | 1042 Node* is_star = WordEqual(target_bytecode, star_bytecode); |
| 1043 BranchIf(is_star, &do_inline_star, &done); | 1043 Branch(is_star, &do_inline_star, &done); |
| 1044 | 1044 |
| 1045 Bind(&do_inline_star); | 1045 Bind(&do_inline_star); |
| 1046 { | 1046 { |
| 1047 InlineStar(); | 1047 InlineStar(); |
| 1048 var_bytecode.Bind(LoadBytecode(BytecodeOffset())); | 1048 var_bytecode.Bind(LoadBytecode(BytecodeOffset())); |
| 1049 Goto(&done); | 1049 Goto(&done); |
| 1050 } | 1050 } |
| 1051 Bind(&done); | 1051 Bind(&done); |
| 1052 return var_bytecode.value(); | 1052 return var_bytecode.value(); |
| 1053 } | 1053 } |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1234 void InterpreterAssembler::Abort(BailoutReason bailout_reason) { | 1234 void InterpreterAssembler::Abort(BailoutReason bailout_reason) { |
| 1235 disable_stack_check_across_call_ = true; | 1235 disable_stack_check_across_call_ = true; |
| 1236 Node* abort_id = SmiTag(Int32Constant(bailout_reason)); | 1236 Node* abort_id = SmiTag(Int32Constant(bailout_reason)); |
| 1237 CallRuntime(Runtime::kAbort, GetContext(), abort_id); | 1237 CallRuntime(Runtime::kAbort, GetContext(), abort_id); |
| 1238 disable_stack_check_across_call_ = false; | 1238 disable_stack_check_across_call_ = false; |
| 1239 } | 1239 } |
| 1240 | 1240 |
| 1241 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, | 1241 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs, |
| 1242 BailoutReason bailout_reason) { | 1242 BailoutReason bailout_reason) { |
| 1243 Label ok(this), abort(this, Label::kDeferred); | 1243 Label ok(this), abort(this, Label::kDeferred); |
| 1244 BranchIfWordEqual(lhs, rhs, &ok, &abort); | 1244 Branch(WordEqual(lhs, rhs), &ok, &abort); |
| 1245 | 1245 |
| 1246 Bind(&abort); | 1246 Bind(&abort); |
| 1247 Abort(bailout_reason); | 1247 Abort(bailout_reason); |
| 1248 Goto(&ok); | 1248 Goto(&ok); |
| 1249 | 1249 |
| 1250 Bind(&ok); | 1250 Bind(&ok); |
| 1251 } | 1251 } |
| 1252 | 1252 |
| 1253 void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) { | 1253 void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) { |
| 1254 CallRuntime(function_id, GetContext(), BytecodeArrayTaggedPointer(), | 1254 CallRuntime(function_id, GetContext(), BytecodeArrayTaggedPointer(), |
| 1255 SmiTag(BytecodeOffset()), GetAccumulatorUnchecked()); | 1255 SmiTag(BytecodeOffset()), GetAccumulatorUnchecked()); |
| 1256 } | 1256 } |
| 1257 | 1257 |
| 1258 void InterpreterAssembler::TraceBytecodeDispatch(Node* target_bytecode) { | 1258 void InterpreterAssembler::TraceBytecodeDispatch(Node* target_bytecode) { |
| 1259 Node* counters_table = ExternalConstant( | 1259 Node* counters_table = ExternalConstant( |
| 1260 ExternalReference::interpreter_dispatch_counters(isolate())); | 1260 ExternalReference::interpreter_dispatch_counters(isolate())); |
| 1261 Node* source_bytecode_table_index = IntPtrConstant( | 1261 Node* source_bytecode_table_index = IntPtrConstant( |
| 1262 static_cast<int>(bytecode_) * (static_cast<int>(Bytecode::kLast) + 1)); | 1262 static_cast<int>(bytecode_) * (static_cast<int>(Bytecode::kLast) + 1)); |
| 1263 | 1263 |
| 1264 Node* counter_offset = | 1264 Node* counter_offset = |
| 1265 WordShl(IntPtrAdd(source_bytecode_table_index, target_bytecode), | 1265 WordShl(IntPtrAdd(source_bytecode_table_index, target_bytecode), |
| 1266 IntPtrConstant(kPointerSizeLog2)); | 1266 IntPtrConstant(kPointerSizeLog2)); |
| 1267 Node* old_counter = | 1267 Node* old_counter = |
| 1268 Load(MachineType::IntPtr(), counters_table, counter_offset); | 1268 Load(MachineType::IntPtr(), counters_table, counter_offset); |
| 1269 | 1269 |
| 1270 Label counter_ok(this), counter_saturated(this, Label::kDeferred); | 1270 Label counter_ok(this), counter_saturated(this, Label::kDeferred); |
| 1271 | 1271 |
| 1272 Node* counter_reached_max = WordEqual( | 1272 Node* counter_reached_max = WordEqual( |
| 1273 old_counter, IntPtrConstant(std::numeric_limits<uintptr_t>::max())); | 1273 old_counter, IntPtrConstant(std::numeric_limits<uintptr_t>::max())); |
| 1274 BranchIf(counter_reached_max, &counter_saturated, &counter_ok); | 1274 Branch(counter_reached_max, &counter_saturated, &counter_ok); |
| 1275 | 1275 |
| 1276 Bind(&counter_ok); | 1276 Bind(&counter_ok); |
| 1277 { | 1277 { |
| 1278 Node* new_counter = IntPtrAdd(old_counter, IntPtrConstant(1)); | 1278 Node* new_counter = IntPtrAdd(old_counter, IntPtrConstant(1)); |
| 1279 StoreNoWriteBarrier(MachineType::PointerRepresentation(), counters_table, | 1279 StoreNoWriteBarrier(MachineType::PointerRepresentation(), counters_table, |
| 1280 counter_offset, new_counter); | 1280 counter_offset, new_counter); |
| 1281 Goto(&counter_saturated); | 1281 Goto(&counter_saturated); |
| 1282 } | 1282 } |
| 1283 | 1283 |
| 1284 Bind(&counter_saturated); | 1284 Bind(&counter_saturated); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1371 Goto(&loop); | 1371 Goto(&loop); |
| 1372 } | 1372 } |
| 1373 Bind(&done_loop); | 1373 Bind(&done_loop); |
| 1374 | 1374 |
| 1375 return array; | 1375 return array; |
| 1376 } | 1376 } |
| 1377 | 1377 |
| 1378 } // namespace interpreter | 1378 } // namespace interpreter |
| 1379 } // namespace internal | 1379 } // namespace internal |
| 1380 } // namespace v8 | 1380 } // namespace v8 |
| OLD | NEW |