| 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/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
| 6 | 6 |
| 7 #include <stack> | 7 #include <stack> |
| 8 | 8 |
| 9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
| 10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
| (...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 | 917 |
| 918 void BytecodeGenerator::VisitProperty(Property* expr) { | 918 void BytecodeGenerator::VisitProperty(Property* expr) { |
| 919 TemporaryRegisterScope temporary_register_scope(builder()); | 919 TemporaryRegisterScope temporary_register_scope(builder()); |
| 920 Register obj = temporary_register_scope.NewRegister(); | 920 Register obj = temporary_register_scope.NewRegister(); |
| 921 Visit(expr->obj()); | 921 Visit(expr->obj()); |
| 922 builder()->StoreAccumulatorInRegister(obj); | 922 builder()->StoreAccumulatorInRegister(obj); |
| 923 VisitPropertyLoad(obj, expr); | 923 VisitPropertyLoad(obj, expr); |
| 924 } | 924 } |
| 925 | 925 |
| 926 | 926 |
| 927 Register BytecodeGenerator::VisitArguments( | |
| 928 ZoneList<Expression*>* args, TemporaryRegisterScope* register_scope) { | |
| 929 // Visit arguments and place in a contiguous block of temporary registers. | |
| 930 // Return the first temporary register corresponding to the first argument. | |
| 931 DCHECK_GT(args->length(), 0); | |
| 932 Register first_arg = register_scope->NewRegister(); | |
| 933 Visit(args->at(0)); | |
| 934 builder()->StoreAccumulatorInRegister(first_arg); | |
| 935 for (int i = 1; i < static_cast<int>(args->length()); i++) { | |
| 936 Register ith_arg = register_scope->NewRegister(); | |
| 937 Visit(args->at(i)); | |
| 938 builder()->StoreAccumulatorInRegister(ith_arg); | |
| 939 DCHECK(ith_arg.index() - i == first_arg.index()); | |
| 940 } | |
| 941 | |
| 942 return first_arg; | |
| 943 } | |
| 944 | |
| 945 | |
| 946 void BytecodeGenerator::VisitCall(Call* expr) { | 927 void BytecodeGenerator::VisitCall(Call* expr) { |
| 947 Expression* callee_expr = expr->expression(); | 928 Expression* callee_expr = expr->expression(); |
| 948 Call::CallType call_type = expr->GetCallType(isolate()); | 929 Call::CallType call_type = expr->GetCallType(isolate()); |
| 949 | 930 |
| 950 // Prepare the callee and the receiver to the function call. This depends on | 931 // Prepare the callee and the receiver to the function call. This depends on |
| 951 // the semantics of the underlying call type. | 932 // the semantics of the underlying call type. |
| 952 TemporaryRegisterScope temporary_register_scope(builder()); | 933 TemporaryRegisterScope temporary_register_scope(builder()); |
| 953 Register callee = temporary_register_scope.NewRegister(); | 934 Register callee = temporary_register_scope.NewRegister(); |
| 954 Register receiver = temporary_register_scope.NewRegister(); | 935 Register receiver = temporary_register_scope.NewRegister(); |
| 955 | 936 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 983 } | 964 } |
| 984 case Call::LOOKUP_SLOT_CALL: | 965 case Call::LOOKUP_SLOT_CALL: |
| 985 case Call::SUPER_CALL: | 966 case Call::SUPER_CALL: |
| 986 case Call::POSSIBLY_EVAL_CALL: | 967 case Call::POSSIBLY_EVAL_CALL: |
| 987 UNIMPLEMENTED(); | 968 UNIMPLEMENTED(); |
| 988 } | 969 } |
| 989 | 970 |
| 990 // Evaluate all arguments to the function call and store in sequential | 971 // Evaluate all arguments to the function call and store in sequential |
| 991 // registers. | 972 // registers. |
| 992 ZoneList<Expression*>* args = expr->arguments(); | 973 ZoneList<Expression*>* args = expr->arguments(); |
| 993 if (args->length() > 0) { | 974 for (int i = 0; i < args->length(); ++i) { |
| 994 Register first_arg = VisitArguments(args, &temporary_register_scope); | 975 Visit(args->at(i)); |
| 995 CHECK_EQ(first_arg.index(), receiver.index() + 1); | 976 Register arg = temporary_register_scope.NewRegister(); |
| 977 DCHECK(arg.index() - i == receiver.index() + 1); |
| 978 builder()->StoreAccumulatorInRegister(arg); |
| 996 } | 979 } |
| 997 | 980 |
| 998 // TODO(rmcilroy): Deal with possible direct eval here? | 981 // TODO(rmcilroy): Deal with possible direct eval here? |
| 999 // TODO(rmcilroy): Use CallIC to allow call type feedback. | 982 // TODO(rmcilroy): Use CallIC to allow call type feedback. |
| 1000 builder()->Call(callee, receiver, args->length()); | 983 builder()->Call(callee, receiver, args->length()); |
| 1001 } | 984 } |
| 1002 | 985 |
| 1003 | 986 |
| 1004 void BytecodeGenerator::VisitCallNew(CallNew* expr) { | 987 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } |
| 1005 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 1006 Register constructor = temporary_register_scope.NewRegister(); | |
| 1007 Visit(expr->expression()); | |
| 1008 builder()->StoreAccumulatorInRegister(constructor); | |
| 1009 ZoneList<Expression*>* args = expr->arguments(); | |
| 1010 if (args->length() > 0) { | |
| 1011 Register first_arg = VisitArguments(args, &temporary_register_scope); | |
| 1012 builder()->New(constructor, first_arg, args->length()); | |
| 1013 } else { | |
| 1014 // The second argument here will be ignored as there are zero | |
| 1015 // arguments. Using the constructor register avoids avoid | |
| 1016 // allocating a temporary just to fill the operands. | |
| 1017 builder()->New(constructor, constructor, 0); | |
| 1018 } | |
| 1019 } | |
| 1020 | 988 |
| 1021 | 989 |
| 1022 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 990 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 1023 if (expr->is_jsruntime()) { | 991 if (expr->is_jsruntime()) { |
| 1024 UNIMPLEMENTED(); | 992 UNIMPLEMENTED(); |
| 1025 } | 993 } |
| 1026 | 994 |
| 1027 // Evaluate all arguments to the runtime call. | 995 // Evaluate all arguments to the runtime call. |
| 1028 TemporaryRegisterScope temporary_register_scope(&builder_); | 996 ZoneList<Expression*>* args = expr->arguments(); |
| 997 TemporaryRegisterScope temporary_register_scope(builder()); |
| 998 // Ensure we always have a valid first_arg register even if there are no |
| 999 // arguments to pass. |
| 1000 Register first_arg = temporary_register_scope.NewRegister(); |
| 1001 for (int i = 0; i < args->length(); ++i) { |
| 1002 Register arg = |
| 1003 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); |
| 1004 Visit(args->at(i)); |
| 1005 DCHECK_EQ(arg.index() - i, first_arg.index()); |
| 1006 builder()->StoreAccumulatorInRegister(arg); |
| 1007 } |
| 1029 | 1008 |
| 1030 // TODO(rmcilroy): support multiple return values. | 1009 // TODO(rmcilroy): support multiple return values. |
| 1031 DCHECK_LE(expr->function()->result_size, 1); | 1010 DCHECK_LE(expr->function()->result_size, 1); |
| 1032 Runtime::FunctionId function_id = expr->function()->function_id; | 1011 Runtime::FunctionId function_id = expr->function()->function_id; |
| 1033 ZoneList<Expression*>* args = expr->arguments(); | |
| 1034 Register first_arg; | |
| 1035 if (args->length() > 0) { | |
| 1036 first_arg = VisitArguments(args, &temporary_register_scope); | |
| 1037 } else { | |
| 1038 // Allocation here is just to fullfil the requirement that there | |
| 1039 // is a register operand for the start of the arguments though | |
| 1040 // there are zero when this is generated. | |
| 1041 first_arg = temporary_register_scope.NewRegister(); | |
| 1042 } | |
| 1043 builder()->CallRuntime(function_id, first_arg, args->length()); | 1012 builder()->CallRuntime(function_id, first_arg, args->length()); |
| 1044 } | 1013 } |
| 1045 | 1014 |
| 1046 | 1015 |
| 1047 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { | 1016 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { |
| 1048 Visit(expr->expression()); | 1017 Visit(expr->expression()); |
| 1049 builder()->LoadUndefined(); | 1018 builder()->LoadUndefined(); |
| 1050 } | 1019 } |
| 1051 | 1020 |
| 1052 | 1021 |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1286 } | 1255 } |
| 1287 | 1256 |
| 1288 | 1257 |
| 1289 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 1258 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 1290 return info()->feedback_vector()->GetIndex(slot); | 1259 return info()->feedback_vector()->GetIndex(slot); |
| 1291 } | 1260 } |
| 1292 | 1261 |
| 1293 } // namespace interpreter | 1262 } // namespace interpreter |
| 1294 } // namespace internal | 1263 } // namespace internal |
| 1295 } // namespace v8 | 1264 } // namespace v8 |
| OLD | NEW |