| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 | 77 |
| 78 { Comment cmnt(masm_, "[ Declarations"); | 78 { Comment cmnt(masm_, "[ Declarations"); |
| 79 VisitDeclarations(fun->scope()->declarations()); | 79 VisitDeclarations(fun->scope()->declarations()); |
| 80 } | 80 } |
| 81 | 81 |
| 82 if (FLAG_trace) { | 82 if (FLAG_trace) { |
| 83 __ CallRuntime(Runtime::kTraceEnter, 0); | 83 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 84 } | 84 } |
| 85 | 85 |
| 86 { Comment cmnt(masm_, "[ Body"); | 86 { Comment cmnt(masm_, "[ Body"); |
| 87 ASSERT(loop_depth() == 0); |
| 87 VisitStatements(fun->body()); | 88 VisitStatements(fun->body()); |
| 89 ASSERT(loop_depth() == 0); |
| 88 } | 90 } |
| 89 | 91 |
| 90 { Comment cmnt(masm_, "[ return <undefined>;"); | 92 { Comment cmnt(masm_, "[ return <undefined>;"); |
| 91 // Emit a 'return undefined' in case control fell off the end of the | 93 // Emit a 'return undefined' in case control fell off the end of the |
| 92 // body. | 94 // body. |
| 93 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 95 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 94 } | 96 } |
| 95 { Comment cmnt(masm_, "Return sequence"); | 97 { Comment cmnt(masm_, "Return sequence"); |
| 96 SetReturnPosition(fun); | 98 SetReturnPosition(fun); |
| 97 | 99 |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 // is no test rax instruction here. | 355 // is no test rax instruction here. |
| 354 DropAndMove(expr->context(), rax); | 356 DropAndMove(expr->context(), rax); |
| 355 } else { | 357 } else { |
| 356 Comment cmnt(masm_, "Stack slot"); | 358 Comment cmnt(masm_, "Stack slot"); |
| 357 Move(expr->context(), rewrite->AsSlot()); | 359 Move(expr->context(), rewrite->AsSlot()); |
| 358 } | 360 } |
| 359 } | 361 } |
| 360 | 362 |
| 361 | 363 |
| 362 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 364 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 363 Comment cmnt(masm_, "[ RegExp Literal"); | 365 Comment cmnt(masm_, "[ RegExpLiteral"); |
| 364 Label done; | 366 Label done; |
| 365 // Registers will be used as follows: | 367 // Registers will be used as follows: |
| 366 // rdi = JS function. | 368 // rdi = JS function. |
| 367 // rbx = literals array. | 369 // rbx = literals array. |
| 368 // rax = regexp literal. | 370 // rax = regexp literal. |
| 369 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 371 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 370 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); | 372 __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); |
| 371 int literal_offset = | 373 int literal_offset = |
| 372 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 374 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
| 373 __ movq(rax, FieldOperand(rbx, literal_offset)); | 375 __ movq(rax, FieldOperand(rbx, literal_offset)); |
| (...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 __ push(rax); | 850 __ push(rax); |
| 849 // Push receiver object on stack. | 851 // Push receiver object on stack. |
| 850 if (prop->is_synthetic()) { | 852 if (prop->is_synthetic()) { |
| 851 __ push(CodeGenerator::GlobalObject()); | 853 __ push(CodeGenerator::GlobalObject()); |
| 852 } else { | 854 } else { |
| 853 __ push(rbx); | 855 __ push(rbx); |
| 854 } | 856 } |
| 855 EmitCallWithStub(expr); | 857 EmitCallWithStub(expr); |
| 856 } | 858 } |
| 857 } else { | 859 } else { |
| 858 // Call to some other function expression. | 860 // Call to some other expression. If the expression is an anonymous |
| 859 Visit(expr->expression()); | 861 // function literal not called in a loop, mark it as one that should |
| 862 // also use the fast code generator. |
| 863 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
| 864 if (lit != NULL && |
| 865 lit->name()->Equals(Heap::empty_string()) && |
| 866 loop_depth() == 0) { |
| 867 lit->mark_as_fast(); |
| 868 } |
| 869 Visit(fun); |
| 860 // Load global receiver object. | 870 // Load global receiver object. |
| 861 __ movq(rbx, CodeGenerator::GlobalObject()); | 871 __ movq(rbx, CodeGenerator::GlobalObject()); |
| 862 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | 872 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); |
| 863 // Emit function call. | 873 // Emit function call. |
| 864 EmitCallWithStub(expr); | 874 EmitCallWithStub(expr); |
| 865 } | 875 } |
| 866 } | 876 } |
| 867 | 877 |
| 868 | 878 |
| 869 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 879 void FastCodeGenerator::VisitCallNew(CallNew* expr) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 for (int i = 0; i < arg_count; i++) { | 928 for (int i = 0; i < arg_count; i++) { |
| 919 Visit(args->at(i)); | 929 Visit(args->at(i)); |
| 920 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 930 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
| 921 } | 931 } |
| 922 | 932 |
| 923 __ CallRuntime(function, arg_count); | 933 __ CallRuntime(function, arg_count); |
| 924 Move(expr->context(), rax); | 934 Move(expr->context(), rax); |
| 925 } | 935 } |
| 926 | 936 |
| 927 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 937 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 928 VariableProxy* v = expr->expression()->AsVariableProxy(); | 938 Comment cmnt(masm_, "[ CountOperation"); |
| 929 ASSERT(v->AsVariable() != NULL); | 939 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 930 ASSERT(v->AsVariable()->is_global()); | 940 ASSERT(proxy->AsVariable() != NULL); |
| 941 ASSERT(proxy->AsVariable()->is_global()); |
| 931 | 942 |
| 932 Visit(v); | 943 Visit(proxy); |
| 933 | |
| 934 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 944 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
| 935 | 945 |
| 936 switch (expr->context()) { | 946 switch (expr->context()) { |
| 937 case Expression::kUninitialized: | 947 case Expression::kUninitialized: |
| 938 UNREACHABLE(); | 948 UNREACHABLE(); |
| 939 case Expression::kValue: // Fall through | 949 case Expression::kValue: // Fall through |
| 940 case Expression::kTest: // Fall through | 950 case Expression::kTest: // Fall through |
| 941 case Expression::kTestValue: // Fall through | 951 case Expression::kTestValue: // Fall through |
| 942 case Expression::kValueTest: | 952 case Expression::kValueTest: |
| 943 // Duplicate the result on the stack. | 953 // Duplicate the result on the stack. |
| 944 __ push(rax); | 954 __ push(rax); |
| 945 break; | 955 break; |
| 946 case Expression::kEffect: | 956 case Expression::kEffect: |
| 947 // Do not save result. | 957 // Do not save result. |
| 948 break; | 958 break; |
| 949 } | 959 } |
| 950 // Call runtime for +1/-1. | 960 // Call runtime for +1/-1. |
| 951 __ push(rax); | 961 __ push(rax); |
| 952 __ Push(Smi::FromInt(1)); | 962 __ Push(Smi::FromInt(1)); |
| 953 if (expr->op() == Token::INC) { | 963 if (expr->op() == Token::INC) { |
| 954 __ CallRuntime(Runtime::kNumberAdd, 2); | 964 __ CallRuntime(Runtime::kNumberAdd, 2); |
| 955 } else { | 965 } else { |
| 956 __ CallRuntime(Runtime::kNumberSub, 2); | 966 __ CallRuntime(Runtime::kNumberSub, 2); |
| 957 } | 967 } |
| 958 // Call Store IC. | 968 // Call Store IC. |
| 959 __ Move(rcx, v->AsVariable()->name()); | 969 __ Move(rcx, proxy->AsVariable()->name()); |
| 960 __ push(CodeGenerator::GlobalObject()); | 970 __ push(CodeGenerator::GlobalObject()); |
| 961 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 971 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 962 __ call(ic, RelocInfo::CODE_TARGET); | 972 __ call(ic, RelocInfo::CODE_TARGET); |
| 963 // Restore up stack after store IC | 973 // Restore up stack after store IC |
| 964 __ addq(rsp, Immediate(kPointerSize)); | 974 __ addq(rsp, Immediate(kPointerSize)); |
| 965 | 975 |
| 966 switch (expr->context()) { | 976 switch (expr->context()) { |
| 967 case Expression::kUninitialized: | 977 case Expression::kUninitialized: |
| 968 UNREACHABLE(); | 978 UNREACHABLE(); |
| 969 case Expression::kEffect: // Fall through | 979 case Expression::kEffect: // Fall through |
| (...skipping 22 matching lines...) Expand all Loading... |
| 992 __ addq(rsp, Immediate(kPointerSize)); | 1002 __ addq(rsp, Immediate(kPointerSize)); |
| 993 __ jmp(true_label_); | 1003 __ jmp(true_label_); |
| 994 break; | 1004 break; |
| 995 } | 1005 } |
| 996 } | 1006 } |
| 997 } | 1007 } |
| 998 | 1008 |
| 999 | 1009 |
| 1000 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1010 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 1001 Comment cmnt(masm_, "[ UnaryOperation"); | 1011 Comment cmnt(masm_, "[ UnaryOperation"); |
| 1002 | |
| 1003 switch (expr->op()) { | 1012 switch (expr->op()) { |
| 1004 case Token::VOID: | 1013 case Token::VOID: |
| 1005 Visit(expr->expression()); | 1014 Visit(expr->expression()); |
| 1006 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1015 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); |
| 1007 switch (expr->context()) { | 1016 switch (expr->context()) { |
| 1008 case Expression::kUninitialized: | 1017 case Expression::kUninitialized: |
| 1009 UNREACHABLE(); | 1018 UNREACHABLE(); |
| 1010 break; | 1019 break; |
| 1011 case Expression::kEffect: | 1020 case Expression::kEffect: |
| 1012 break; | 1021 break; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 break; | 1094 break; |
| 1086 } | 1095 } |
| 1087 | 1096 |
| 1088 default: | 1097 default: |
| 1089 UNREACHABLE(); | 1098 UNREACHABLE(); |
| 1090 } | 1099 } |
| 1091 } | 1100 } |
| 1092 | 1101 |
| 1093 | 1102 |
| 1094 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1103 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 1104 Comment cmnt(masm_, "[ BinaryOperation"); |
| 1095 switch (expr->op()) { | 1105 switch (expr->op()) { |
| 1096 case Token::COMMA: | 1106 case Token::COMMA: |
| 1097 ASSERT_EQ(Expression::kEffect, expr->left()->context()); | 1107 ASSERT_EQ(Expression::kEffect, expr->left()->context()); |
| 1098 ASSERT_EQ(expr->context(), expr->right()->context()); | 1108 ASSERT_EQ(expr->context(), expr->right()->context()); |
| 1099 Visit(expr->left()); | 1109 Visit(expr->left()); |
| 1100 Visit(expr->right()); | 1110 Visit(expr->right()); |
| 1101 break; | 1111 break; |
| 1102 | 1112 |
| 1103 case Token::OR: | 1113 case Token::OR: |
| 1104 case Token::AND: | 1114 case Token::AND: |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1129 | 1139 |
| 1130 break; | 1140 break; |
| 1131 } | 1141 } |
| 1132 default: | 1142 default: |
| 1133 UNREACHABLE(); | 1143 UNREACHABLE(); |
| 1134 } | 1144 } |
| 1135 } | 1145 } |
| 1136 | 1146 |
| 1137 | 1147 |
| 1138 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1148 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 1149 Comment cmnt(masm_, "[ CompareOperation"); |
| 1139 ASSERT_EQ(Expression::kValue, expr->left()->context()); | 1150 ASSERT_EQ(Expression::kValue, expr->left()->context()); |
| 1140 ASSERT_EQ(Expression::kValue, expr->right()->context()); | 1151 ASSERT_EQ(Expression::kValue, expr->right()->context()); |
| 1141 Visit(expr->left()); | 1152 Visit(expr->left()); |
| 1142 Visit(expr->right()); | 1153 Visit(expr->right()); |
| 1143 | 1154 |
| 1144 // Convert current context to test context: Pre-test code. | 1155 // Convert current context to test context: Pre-test code. |
| 1145 Label push_true; | 1156 Label push_true; |
| 1146 Label push_false; | 1157 Label push_false; |
| 1147 Label done; | 1158 Label done; |
| 1148 Label* saved_true = true_label_; | 1159 Label* saved_true = true_label_; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1287 true_label_ = saved_true; | 1298 true_label_ = saved_true; |
| 1288 false_label_ = saved_false; | 1299 false_label_ = saved_false; |
| 1289 // Convert current context to test context: End post-test code. | 1300 // Convert current context to test context: End post-test code. |
| 1290 } | 1301 } |
| 1291 | 1302 |
| 1292 | 1303 |
| 1293 #undef __ | 1304 #undef __ |
| 1294 | 1305 |
| 1295 | 1306 |
| 1296 } } // namespace v8::internal | 1307 } } // namespace v8::internal |
| OLD | NEW |