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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 StackCheckStub stub; | 78 StackCheckStub stub; |
79 __ CallStub(&stub); | 79 __ CallStub(&stub); |
80 __ bind(&ok); | 80 __ bind(&ok); |
81 } | 81 } |
82 | 82 |
83 if (FLAG_trace) { | 83 if (FLAG_trace) { |
84 __ CallRuntime(Runtime::kTraceEnter, 0); | 84 __ CallRuntime(Runtime::kTraceEnter, 0); |
85 } | 85 } |
86 | 86 |
87 { Comment cmnt(masm_, "[ Body"); | 87 { Comment cmnt(masm_, "[ Body"); |
| 88 ASSERT(loop_depth() == 0); |
88 VisitStatements(fun->body()); | 89 VisitStatements(fun->body()); |
| 90 ASSERT(loop_depth() == 0); |
89 } | 91 } |
90 | 92 |
91 { Comment cmnt(masm_, "[ return <undefined>;"); | 93 { Comment cmnt(masm_, "[ return <undefined>;"); |
92 // Emit a 'return undefined' in case control fell off the end of the | 94 // Emit a 'return undefined' in case control fell off the end of the |
93 // body. | 95 // body. |
94 __ mov(eax, Factory::undefined_value()); | 96 __ mov(eax, Factory::undefined_value()); |
95 } | 97 } |
96 { Comment cmnt(masm_, "[ Return sequence"); | 98 { Comment cmnt(masm_, "[ Return sequence"); |
97 SetReturnPosition(fun); | 99 SetReturnPosition(fun); |
98 | 100 |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 | 337 |
336 DropAndMove(expr->context(), eax); | 338 DropAndMove(expr->context(), eax); |
337 } else { | 339 } else { |
338 Comment cmnt(masm_, "Stack slot"); | 340 Comment cmnt(masm_, "Stack slot"); |
339 Move(expr->context(), rewrite->AsSlot()); | 341 Move(expr->context(), rewrite->AsSlot()); |
340 } | 342 } |
341 } | 343 } |
342 | 344 |
343 | 345 |
344 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 346 void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
345 Comment cmnt(masm_, "[ RegExp Literal"); | 347 Comment cmnt(masm_, "[ RegExpLiteral"); |
346 Label done; | 348 Label done; |
347 // Registers will be used as follows: | 349 // Registers will be used as follows: |
348 // edi = JS function. | 350 // edi = JS function. |
349 // ebx = literals array. | 351 // ebx = literals array. |
350 // eax = regexp literal. | 352 // eax = regexp literal. |
351 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 353 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
352 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 354 __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
353 int literal_offset = | 355 int literal_offset = |
354 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; | 356 FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; |
355 __ mov(eax, FieldOperand(ebx, literal_offset)); | 357 __ mov(eax, FieldOperand(ebx, literal_offset)); |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 __ push(eax); | 835 __ push(eax); |
834 // Push receiver object on stack. | 836 // Push receiver object on stack. |
835 if (prop->is_synthetic()) { | 837 if (prop->is_synthetic()) { |
836 __ push(CodeGenerator::GlobalObject()); | 838 __ push(CodeGenerator::GlobalObject()); |
837 } else { | 839 } else { |
838 __ push(ebx); | 840 __ push(ebx); |
839 } | 841 } |
840 EmitCallWithStub(expr); | 842 EmitCallWithStub(expr); |
841 } | 843 } |
842 } else { | 844 } else { |
843 // Call to some other function expression. | 845 // Call to some other expression. If the expression is an anonymous |
844 Visit(expr->expression()); | 846 // function literal not called in a loop, mark it as one that should |
| 847 // also use the fast code generator. |
| 848 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
| 849 if (lit != NULL && |
| 850 lit->name()->Equals(Heap::empty_string()) && |
| 851 loop_depth() == 0) { |
| 852 lit->mark_as_fast(); |
| 853 } |
| 854 Visit(fun); |
845 // Load global receiver object. | 855 // Load global receiver object. |
846 __ mov(ebx, CodeGenerator::GlobalObject()); | 856 __ mov(ebx, CodeGenerator::GlobalObject()); |
847 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); | 857 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset)); |
848 // Emit function call. | 858 // Emit function call. |
849 EmitCallWithStub(expr); | 859 EmitCallWithStub(expr); |
850 } | 860 } |
851 } | 861 } |
852 | 862 |
| 863 |
853 void FastCodeGenerator::VisitCallNew(CallNew* expr) { | 864 void FastCodeGenerator::VisitCallNew(CallNew* expr) { |
854 Comment cmnt(masm_, "[ CallNew"); | 865 Comment cmnt(masm_, "[ CallNew"); |
855 // According to ECMA-262, section 11.2.2, page 44, the function | 866 // According to ECMA-262, section 11.2.2, page 44, the function |
856 // expression in new calls must be evaluated before the | 867 // expression in new calls must be evaluated before the |
857 // arguments. | 868 // arguments. |
858 // Push function on the stack. | 869 // Push function on the stack. |
859 Visit(expr->expression()); | 870 Visit(expr->expression()); |
860 ASSERT_EQ(Expression::kValue, expr->expression()->context()); | 871 ASSERT_EQ(Expression::kValue, expr->expression()->context()); |
861 | 872 |
862 // Push global object (receiver). | 873 // Push global object (receiver). |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
903 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 914 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
904 } | 915 } |
905 | 916 |
906 __ CallRuntime(function, arg_count); | 917 __ CallRuntime(function, arg_count); |
907 Move(expr->context(), eax); | 918 Move(expr->context(), eax); |
908 } | 919 } |
909 | 920 |
910 | 921 |
911 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 922 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
912 Comment cmnt(masm_, "[ UnaryOperation"); | 923 Comment cmnt(masm_, "[ UnaryOperation"); |
913 | |
914 switch (expr->op()) { | 924 switch (expr->op()) { |
915 case Token::VOID: | 925 case Token::VOID: |
916 Visit(expr->expression()); | 926 Visit(expr->expression()); |
917 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 927 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); |
918 switch (expr->context()) { | 928 switch (expr->context()) { |
919 case Expression::kUninitialized: | 929 case Expression::kUninitialized: |
920 UNREACHABLE(); | 930 UNREACHABLE(); |
921 break; | 931 break; |
922 case Expression::kEffect: | 932 case Expression::kEffect: |
923 break; | 933 break; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 break; | 1006 break; |
997 } | 1007 } |
998 | 1008 |
999 default: | 1009 default: |
1000 UNREACHABLE(); | 1010 UNREACHABLE(); |
1001 } | 1011 } |
1002 } | 1012 } |
1003 | 1013 |
1004 | 1014 |
1005 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1015 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
1006 VariableProxy* v = expr->expression()->AsVariableProxy(); | 1016 Comment cmnt(masm_, "[ CountOperation"); |
1007 ASSERT(v->AsVariable() != NULL); | 1017 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
1008 ASSERT(v->AsVariable()->is_global()); | 1018 ASSERT(proxy->AsVariable() != NULL); |
| 1019 ASSERT(proxy->AsVariable()->is_global()); |
1009 | 1020 |
1010 Visit(v); | 1021 Visit(proxy); |
1011 | |
1012 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); | 1022 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); |
1013 | 1023 |
1014 switch (expr->context()) { | 1024 switch (expr->context()) { |
1015 case Expression::kUninitialized: | 1025 case Expression::kUninitialized: |
1016 UNREACHABLE(); | 1026 UNREACHABLE(); |
1017 case Expression::kValue: // Fall through | 1027 case Expression::kValue: // Fall through |
1018 case Expression::kTest: // Fall through | 1028 case Expression::kTest: // Fall through |
1019 case Expression::kTestValue: // Fall through | 1029 case Expression::kTestValue: // Fall through |
1020 case Expression::kValueTest: | 1030 case Expression::kValueTest: |
1021 // Duplicate the result on the stack. | 1031 // Duplicate the result on the stack. |
1022 __ push(eax); | 1032 __ push(eax); |
1023 break; | 1033 break; |
1024 case Expression::kEffect: | 1034 case Expression::kEffect: |
1025 // Do not save result. | 1035 // Do not save result. |
1026 break; | 1036 break; |
1027 } | 1037 } |
1028 // Call runtime for +1/-1. | 1038 // Call runtime for +1/-1. |
1029 __ push(eax); | 1039 __ push(eax); |
1030 __ push(Immediate(Smi::FromInt(1))); | 1040 __ push(Immediate(Smi::FromInt(1))); |
1031 if (expr->op() == Token::INC) { | 1041 if (expr->op() == Token::INC) { |
1032 __ CallRuntime(Runtime::kNumberAdd, 2); | 1042 __ CallRuntime(Runtime::kNumberAdd, 2); |
1033 } else { | 1043 } else { |
1034 __ CallRuntime(Runtime::kNumberSub, 2); | 1044 __ CallRuntime(Runtime::kNumberSub, 2); |
1035 } | 1045 } |
1036 // Call Store IC. | 1046 // Call Store IC. |
1037 __ mov(ecx, v->AsVariable()->name()); | 1047 __ mov(ecx, proxy->AsVariable()->name()); |
1038 __ push(CodeGenerator::GlobalObject()); | 1048 __ push(CodeGenerator::GlobalObject()); |
1039 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1049 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1040 __ call(ic, RelocInfo::CODE_TARGET); | 1050 __ call(ic, RelocInfo::CODE_TARGET); |
1041 // Restore up stack after store IC. | 1051 // Restore up stack after store IC. |
1042 __ add(Operand(esp), Immediate(kPointerSize)); | 1052 __ add(Operand(esp), Immediate(kPointerSize)); |
1043 | 1053 |
1044 switch (expr->context()) { | 1054 switch (expr->context()) { |
1045 case Expression::kUninitialized: | 1055 case Expression::kUninitialized: |
1046 UNREACHABLE(); | 1056 UNREACHABLE(); |
1047 case Expression::kEffect: // Fall through | 1057 case Expression::kEffect: // Fall through |
(...skipping 21 matching lines...) Expand all Loading... |
1069 __ bind(&discard); | 1079 __ bind(&discard); |
1070 __ add(Operand(esp), Immediate(kPointerSize)); | 1080 __ add(Operand(esp), Immediate(kPointerSize)); |
1071 __ jmp(true_label_); | 1081 __ jmp(true_label_); |
1072 break; | 1082 break; |
1073 } | 1083 } |
1074 } | 1084 } |
1075 } | 1085 } |
1076 | 1086 |
1077 | 1087 |
1078 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1088 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
| 1089 Comment cmnt(masm_, "[ BinaryOperation"); |
1079 switch (expr->op()) { | 1090 switch (expr->op()) { |
1080 case Token::COMMA: | 1091 case Token::COMMA: |
1081 ASSERT_EQ(Expression::kEffect, expr->left()->context()); | 1092 ASSERT_EQ(Expression::kEffect, expr->left()->context()); |
1082 ASSERT_EQ(expr->context(), expr->right()->context()); | 1093 ASSERT_EQ(expr->context(), expr->right()->context()); |
1083 Visit(expr->left()); | 1094 Visit(expr->left()); |
1084 Visit(expr->right()); | 1095 Visit(expr->right()); |
1085 break; | 1096 break; |
1086 | 1097 |
1087 case Token::OR: | 1098 case Token::OR: |
1088 case Token::AND: | 1099 case Token::AND: |
(...skipping 24 matching lines...) Expand all Loading... |
1113 | 1124 |
1114 break; | 1125 break; |
1115 } | 1126 } |
1116 default: | 1127 default: |
1117 UNREACHABLE(); | 1128 UNREACHABLE(); |
1118 } | 1129 } |
1119 } | 1130 } |
1120 | 1131 |
1121 | 1132 |
1122 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1133 void FastCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 1134 Comment cmnt(masm_, "[ CompareOperation"); |
1123 ASSERT_EQ(Expression::kValue, expr->left()->context()); | 1135 ASSERT_EQ(Expression::kValue, expr->left()->context()); |
1124 ASSERT_EQ(Expression::kValue, expr->right()->context()); | 1136 ASSERT_EQ(Expression::kValue, expr->right()->context()); |
1125 Visit(expr->left()); | 1137 Visit(expr->left()); |
1126 Visit(expr->right()); | 1138 Visit(expr->right()); |
1127 | 1139 |
1128 // Convert current context to test context: Pre-test code. | 1140 // Convert current context to test context: Pre-test code. |
1129 Label push_true; | 1141 Label push_true; |
1130 Label push_false; | 1142 Label push_false; |
1131 Label done; | 1143 Label done; |
1132 Label* saved_true = true_label_; | 1144 Label* saved_true = true_label_; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1274 true_label_ = saved_true; | 1286 true_label_ = saved_true; |
1275 false_label_ = saved_false; | 1287 false_label_ = saved_false; |
1276 // Convert current context to test context: End post-test code. | 1288 // Convert current context to test context: End post-test code. |
1277 } | 1289 } |
1278 | 1290 |
1279 | 1291 |
1280 #undef __ | 1292 #undef __ |
1281 | 1293 |
1282 | 1294 |
1283 } } // namespace v8::internal | 1295 } } // namespace v8::internal |
OLD | NEW |