| 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 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 } | 388 } |
| 389 | 389 |
| 390 Node* InterpreterAssembler::BytecodeOperandUImm(int operand_index) { | 390 Node* InterpreterAssembler::BytecodeOperandUImm(int operand_index) { |
| 391 DCHECK_EQ(OperandType::kUImm, | 391 DCHECK_EQ(OperandType::kUImm, |
| 392 Bytecodes::GetOperandType(bytecode_, operand_index)); | 392 Bytecodes::GetOperandType(bytecode_, operand_index)); |
| 393 OperandSize operand_size = | 393 OperandSize operand_size = |
| 394 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); | 394 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
| 395 return BytecodeUnsignedOperand(operand_index, operand_size); | 395 return BytecodeUnsignedOperand(operand_index, operand_size); |
| 396 } | 396 } |
| 397 | 397 |
| 398 Node* InterpreterAssembler::BytecodeOperandUImmWord(int operand_index) { |
| 399 return ChangeUint32ToWord(BytecodeOperandUImm(operand_index)); |
| 400 } |
| 401 |
| 398 Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) { | 402 Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) { |
| 399 DCHECK_EQ(OperandType::kImm, | 403 DCHECK_EQ(OperandType::kImm, |
| 400 Bytecodes::GetOperandType(bytecode_, operand_index)); | 404 Bytecodes::GetOperandType(bytecode_, operand_index)); |
| 401 OperandSize operand_size = | 405 OperandSize operand_size = |
| 402 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); | 406 Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()); |
| 403 return BytecodeSignedOperand(operand_index, operand_size); | 407 return BytecodeSignedOperand(operand_index, operand_size); |
| 404 } | 408 } |
| 405 | 409 |
| 406 Node* InterpreterAssembler::BytecodeOperandImmIntPtr(int operand_index) { | 410 Node* InterpreterAssembler::BytecodeOperandImmIntPtr(int operand_index) { |
| 407 return ChangeInt32ToIntPtr(BytecodeOperandImm(operand_index)); | 411 return ChangeInt32ToIntPtr(BytecodeOperandImm(operand_index)); |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 875 Node* function = | 879 Node* function = |
| 876 IntPtrAdd(function_table, ChangeUint32ToWord(function_offset)); | 880 IntPtrAdd(function_table, ChangeUint32ToWord(function_offset)); |
| 877 Node* function_entry = | 881 Node* function_entry = |
| 878 Load(MachineType::Pointer(), function, | 882 Load(MachineType::Pointer(), function, |
| 879 IntPtrConstant(offsetof(Runtime::Function, entry))); | 883 IntPtrConstant(offsetof(Runtime::Function, entry))); |
| 880 | 884 |
| 881 return CallStubR(callable.descriptor(), result_size, code_target, context, | 885 return CallStubR(callable.descriptor(), result_size, code_target, context, |
| 882 arg_count, first_arg, function_entry); | 886 arg_count, first_arg, function_entry); |
| 883 } | 887 } |
| 884 | 888 |
| 885 void InterpreterAssembler::UpdateInterruptBudget(Node* weight) { | 889 void InterpreterAssembler::UpdateInterruptBudget(Node* weight, bool backward) { |
| 886 // TODO(rmcilroy): It might be worthwhile to only update the budget for | |
| 887 // backwards branches. Those are distinguishable by the {JumpLoop} bytecode. | |
| 888 | |
| 889 Label ok(this), interrupt_check(this, Label::kDeferred), end(this); | 890 Label ok(this), interrupt_check(this, Label::kDeferred), end(this); |
| 890 Node* budget_offset = | 891 Node* budget_offset = |
| 891 IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag); | 892 IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag); |
| 892 | 893 |
| 893 // Update budget by |weight| and check if it reaches zero. | 894 // Update budget by |weight| and check if it reaches zero. |
| 894 Variable new_budget(this, MachineRepresentation::kWord32); | 895 Variable new_budget(this, MachineRepresentation::kWord32); |
| 895 Node* old_budget = | 896 Node* old_budget = |
| 896 Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset); | 897 Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset); |
| 897 new_budget.Bind(Int32Add(old_budget, weight)); | 898 if (backward) { |
| 899 new_budget.Bind(Int32Sub(old_budget, weight)); |
| 900 } else { |
| 901 new_budget.Bind(Int32Add(old_budget, weight)); |
| 902 } |
| 898 Node* condition = | 903 Node* condition = |
| 899 Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0)); | 904 Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0)); |
| 900 Branch(condition, &ok, &interrupt_check); | 905 Branch(condition, &ok, &interrupt_check); |
| 901 | 906 |
| 902 // Perform interrupt and reset budget. | 907 // Perform interrupt and reset budget. |
| 903 Bind(&interrupt_check); | 908 Bind(&interrupt_check); |
| 904 { | 909 { |
| 905 CallRuntime(Runtime::kInterrupt, GetContext()); | 910 CallRuntime(Runtime::kInterrupt, GetContext()); |
| 906 new_budget.Bind(Int32Constant(Interpreter::InterruptBudget())); | 911 new_budget.Bind(Int32Constant(Interpreter::InterruptBudget())); |
| 907 Goto(&ok); | 912 Goto(&ok); |
| 908 } | 913 } |
| 909 | 914 |
| 910 // Update budget. | 915 // Update budget. |
| 911 Bind(&ok); | 916 Bind(&ok); |
| 912 StoreNoWriteBarrier(MachineRepresentation::kWord32, | 917 StoreNoWriteBarrier(MachineRepresentation::kWord32, |
| 913 BytecodeArrayTaggedPointer(), budget_offset, | 918 BytecodeArrayTaggedPointer(), budget_offset, |
| 914 new_budget.value()); | 919 new_budget.value()); |
| 915 } | 920 } |
| 916 | 921 |
| 917 Node* InterpreterAssembler::Advance() { | 922 Node* InterpreterAssembler::Advance() { |
| 918 return Advance(Bytecodes::Size(bytecode_, operand_scale_)); | 923 return Advance(Bytecodes::Size(bytecode_, operand_scale_)); |
| 919 } | 924 } |
| 920 | 925 |
| 921 Node* InterpreterAssembler::Advance(int delta) { | 926 Node* InterpreterAssembler::Advance(int delta) { |
| 922 return Advance(IntPtrConstant(delta)); | 927 return Advance(IntPtrConstant(delta)); |
| 923 } | 928 } |
| 924 | 929 |
| 925 Node* InterpreterAssembler::Advance(Node* delta) { | 930 Node* InterpreterAssembler::Advance(Node* delta, bool backward) { |
| 926 if (FLAG_trace_ignition) { | 931 if (FLAG_trace_ignition) { |
| 927 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); | 932 TraceBytecode(Runtime::kInterpreterTraceBytecodeExit); |
| 928 } | 933 } |
| 929 Node* next_offset = IntPtrAdd(BytecodeOffset(), delta); | 934 Node* next_offset = backward ? IntPtrSub(BytecodeOffset(), delta) |
| 935 : IntPtrAdd(BytecodeOffset(), delta); |
| 930 bytecode_offset_.Bind(next_offset); | 936 bytecode_offset_.Bind(next_offset); |
| 931 return next_offset; | 937 return next_offset; |
| 932 } | 938 } |
| 933 | 939 |
| 934 Node* InterpreterAssembler::Jump(Node* delta) { | 940 Node* InterpreterAssembler::Jump(Node* delta, bool backward) { |
| 935 DCHECK(!Bytecodes::IsStarLookahead(bytecode_, operand_scale_)); | 941 DCHECK(!Bytecodes::IsStarLookahead(bytecode_, operand_scale_)); |
| 936 | 942 |
| 937 UpdateInterruptBudget(TruncateWordToWord32(delta)); | 943 UpdateInterruptBudget(TruncateWordToWord32(delta), backward); |
| 938 Node* new_bytecode_offset = Advance(delta); | 944 Node* new_bytecode_offset = Advance(delta, backward); |
| 939 Node* target_bytecode = LoadBytecode(new_bytecode_offset); | 945 Node* target_bytecode = LoadBytecode(new_bytecode_offset); |
| 940 return DispatchToBytecode(target_bytecode, new_bytecode_offset); | 946 return DispatchToBytecode(target_bytecode, new_bytecode_offset); |
| 941 } | 947 } |
| 942 | 948 |
| 949 Node* InterpreterAssembler::Jump(Node* delta) { return Jump(delta, false); } |
| 950 |
| 951 Node* InterpreterAssembler::JumpBackward(Node* delta) { |
| 952 return Jump(delta, true); |
| 953 } |
| 954 |
| 943 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) { | 955 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) { |
| 944 Label match(this), no_match(this); | 956 Label match(this), no_match(this); |
| 945 | 957 |
| 946 Branch(condition, &match, &no_match); | 958 Branch(condition, &match, &no_match); |
| 947 Bind(&match); | 959 Bind(&match); |
| 948 Jump(delta); | 960 Jump(delta); |
| 949 Bind(&no_match); | 961 Bind(&no_match); |
| 950 Dispatch(); | 962 Dispatch(); |
| 951 } | 963 } |
| 952 | 964 |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 | 1180 |
| 1169 void InterpreterAssembler::UpdateInterruptBudgetOnReturn() { | 1181 void InterpreterAssembler::UpdateInterruptBudgetOnReturn() { |
| 1170 // TODO(rmcilroy): Investigate whether it is worth supporting self | 1182 // TODO(rmcilroy): Investigate whether it is worth supporting self |
| 1171 // optimization of primitive functions like FullCodegen. | 1183 // optimization of primitive functions like FullCodegen. |
| 1172 | 1184 |
| 1173 // Update profiling count by -BytecodeOffset to simulate backedge to start of | 1185 // Update profiling count by -BytecodeOffset to simulate backedge to start of |
| 1174 // function. | 1186 // function. |
| 1175 Node* profiling_weight = | 1187 Node* profiling_weight = |
| 1176 Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize), | 1188 Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize), |
| 1177 TruncateWordToWord32(BytecodeOffset())); | 1189 TruncateWordToWord32(BytecodeOffset())); |
| 1178 UpdateInterruptBudget(profiling_weight); | 1190 UpdateInterruptBudget(profiling_weight, false); |
| 1179 } | 1191 } |
| 1180 | 1192 |
| 1181 Node* InterpreterAssembler::StackCheckTriggeredInterrupt() { | 1193 Node* InterpreterAssembler::StackCheckTriggeredInterrupt() { |
| 1182 Node* sp = LoadStackPointer(); | 1194 Node* sp = LoadStackPointer(); |
| 1183 Node* stack_limit = Load( | 1195 Node* stack_limit = Load( |
| 1184 MachineType::Pointer(), | 1196 MachineType::Pointer(), |
| 1185 ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); | 1197 ExternalConstant(ExternalReference::address_of_stack_limit(isolate()))); |
| 1186 return UintPtrLessThan(sp, stack_limit); | 1198 return UintPtrLessThan(sp, stack_limit); |
| 1187 } | 1199 } |
| 1188 | 1200 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 Goto(&loop); | 1343 Goto(&loop); |
| 1332 } | 1344 } |
| 1333 Bind(&done_loop); | 1345 Bind(&done_loop); |
| 1334 | 1346 |
| 1335 return array; | 1347 return array; |
| 1336 } | 1348 } |
| 1337 | 1349 |
| 1338 } // namespace interpreter | 1350 } // namespace interpreter |
| 1339 } // namespace internal | 1351 } // namespace internal |
| 1340 } // namespace v8 | 1352 } // namespace v8 |
| OLD | NEW |