| 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 798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 switch (property->kind()) { | 809 switch (property->kind()) { |
| 810 case ObjectLiteral::Property::CONSTANT: | 810 case ObjectLiteral::Property::CONSTANT: |
| 811 UNREACHABLE(); | 811 UNREACHABLE(); |
| 812 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 812 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 813 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); | 813 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 814 // Fall through. | 814 // Fall through. |
| 815 case ObjectLiteral::Property::COMPUTED: | 815 case ObjectLiteral::Property::COMPUTED: |
| 816 if (key->handle()->IsSymbol()) { | 816 if (key->handle()->IsSymbol()) { |
| 817 VisitForValue(value, kAccumulator); | 817 VisitForValue(value, kAccumulator); |
| 818 __ mov(r2, Operand(key->handle())); | 818 __ mov(r2, Operand(key->handle())); |
| 819 __ ldr(r1, MemOperand(sp)); |
| 819 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 820 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 820 __ Call(ic, RelocInfo::CODE_TARGET); | 821 __ Call(ic, RelocInfo::CODE_TARGET); |
| 821 // StoreIC leaves the receiver on the stack. | |
| 822 break; | 822 break; |
| 823 } | 823 } |
| 824 // Fall through. | 824 // Fall through. |
| 825 case ObjectLiteral::Property::PROTOTYPE: | 825 case ObjectLiteral::Property::PROTOTYPE: |
| 826 // Duplicate receiver on stack. | 826 // Duplicate receiver on stack. |
| 827 __ ldr(r0, MemOperand(sp)); | 827 __ ldr(r0, MemOperand(sp)); |
| 828 __ push(r0); | 828 __ push(r0); |
| 829 VisitForValue(key, kStack); | 829 VisitForValue(key, kStack); |
| 830 VisitForValue(value, kStack); | 830 VisitForValue(value, kStack); |
| 831 __ CallRuntime(Runtime::kSetProperty, 3); | 831 __ CallRuntime(Runtime::kSetProperty, 3); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 } | 900 } |
| 901 | 901 |
| 902 if (result_saved) { | 902 if (result_saved) { |
| 903 ApplyTOS(context_); | 903 ApplyTOS(context_); |
| 904 } else { | 904 } else { |
| 905 Apply(context_, r0); | 905 Apply(context_, r0); |
| 906 } | 906 } |
| 907 } | 907 } |
| 908 | 908 |
| 909 | 909 |
| 910 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 911 Comment cmnt(masm_, "[ Assignment"); |
| 912 ASSERT(expr->op() != Token::INIT_CONST); |
| 913 // Left-hand side can only be a property, a global or a (parameter or local) |
| 914 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 915 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 916 LhsKind assign_type = VARIABLE; |
| 917 Property* prop = expr->target()->AsProperty(); |
| 918 if (prop != NULL) { |
| 919 assign_type = |
| 920 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 921 } |
| 922 |
| 923 // Evaluate LHS expression. |
| 924 switch (assign_type) { |
| 925 case VARIABLE: |
| 926 // Nothing to do here. |
| 927 break; |
| 928 case NAMED_PROPERTY: |
| 929 if (expr->is_compound()) { |
| 930 // We need the receiver both on the stack and in the accumulator. |
| 931 VisitForValue(prop->obj(), kAccumulator); |
| 932 __ push(result_register()); |
| 933 } else { |
| 934 VisitForValue(prop->obj(), kStack); |
| 935 } |
| 936 break; |
| 937 case KEYED_PROPERTY: |
| 938 VisitForValue(prop->obj(), kStack); |
| 939 VisitForValue(prop->key(), kStack); |
| 940 break; |
| 941 } |
| 942 |
| 943 // If we have a compound assignment: Get value of LHS expression and |
| 944 // store in on top of the stack. |
| 945 if (expr->is_compound()) { |
| 946 Location saved_location = location_; |
| 947 location_ = kStack; |
| 948 switch (assign_type) { |
| 949 case VARIABLE: |
| 950 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), |
| 951 Expression::kValue); |
| 952 break; |
| 953 case NAMED_PROPERTY: |
| 954 EmitNamedPropertyLoad(prop); |
| 955 __ push(result_register()); |
| 956 break; |
| 957 case KEYED_PROPERTY: |
| 958 EmitKeyedPropertyLoad(prop); |
| 959 __ push(result_register()); |
| 960 break; |
| 961 } |
| 962 location_ = saved_location; |
| 963 } |
| 964 |
| 965 // Evaluate RHS expression. |
| 966 Expression* rhs = expr->value(); |
| 967 VisitForValue(rhs, kAccumulator); |
| 968 |
| 969 // If we have a compound assignment: Apply operator. |
| 970 if (expr->is_compound()) { |
| 971 Location saved_location = location_; |
| 972 location_ = kAccumulator; |
| 973 EmitBinaryOp(expr->binary_op(), Expression::kValue); |
| 974 location_ = saved_location; |
| 975 } |
| 976 |
| 977 // Record source position before possible IC call. |
| 978 SetSourcePosition(expr->position()); |
| 979 |
| 980 // Store the value. |
| 981 switch (assign_type) { |
| 982 case VARIABLE: |
| 983 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
| 984 context_); |
| 985 break; |
| 986 case NAMED_PROPERTY: |
| 987 EmitNamedPropertyAssignment(expr); |
| 988 break; |
| 989 case KEYED_PROPERTY: |
| 990 EmitKeyedPropertyAssignment(expr); |
| 991 break; |
| 992 } |
| 993 } |
| 994 |
| 995 |
| 910 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 996 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 911 SetSourcePosition(prop->position()); | 997 SetSourcePosition(prop->position()); |
| 912 Literal* key = prop->key()->AsLiteral(); | 998 Literal* key = prop->key()->AsLiteral(); |
| 913 __ mov(r2, Operand(key->handle())); | 999 __ mov(r2, Operand(key->handle())); |
| 914 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1000 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 915 __ Call(ic, RelocInfo::CODE_TARGET); | 1001 __ Call(ic, RelocInfo::CODE_TARGET); |
| 916 } | 1002 } |
| 917 | 1003 |
| 918 | 1004 |
| 919 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1005 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 938 // types of slots. Left-hand-side parameters that rewrite to | 1024 // types of slots. Left-hand-side parameters that rewrite to |
| 939 // explicit property accesses do not reach here. | 1025 // explicit property accesses do not reach here. |
| 940 ASSERT(var != NULL); | 1026 ASSERT(var != NULL); |
| 941 ASSERT(var->is_global() || var->slot() != NULL); | 1027 ASSERT(var->is_global() || var->slot() != NULL); |
| 942 | 1028 |
| 943 Slot* slot = var->slot(); | 1029 Slot* slot = var->slot(); |
| 944 if (var->is_global()) { | 1030 if (var->is_global()) { |
| 945 ASSERT(!var->is_this()); | 1031 ASSERT(!var->is_this()); |
| 946 // Assignment to a global variable. Use inline caching for the | 1032 // Assignment to a global variable. Use inline caching for the |
| 947 // assignment. Right-hand-side value is passed in r0, variable name in | 1033 // assignment. Right-hand-side value is passed in r0, variable name in |
| 948 // r2, and the global object on the stack. | 1034 // r2, and the global object in r1. |
| 949 __ mov(r2, Operand(var->name())); | 1035 __ mov(r2, Operand(var->name())); |
| 950 __ ldr(ip, CodeGenerator::GlobalObject()); | 1036 __ ldr(r1, CodeGenerator::GlobalObject()); |
| 951 __ push(ip); | |
| 952 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1037 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 953 __ Call(ic, RelocInfo::CODE_TARGET); | 1038 __ Call(ic, RelocInfo::CODE_TARGET); |
| 954 // Overwrite the global object on the stack with the result if needed. | |
| 955 DropAndApply(1, context, r0); | |
| 956 | 1039 |
| 957 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { | 1040 } else if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| 958 __ push(result_register()); // Value. | 1041 __ push(result_register()); // Value. |
| 959 __ mov(r1, Operand(var->name())); | 1042 __ mov(r1, Operand(var->name())); |
| 960 __ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name. | 1043 __ stm(db_w, sp, cp.bit() | r1.bit()); // Context and name. |
| 961 __ CallRuntime(Runtime::kStoreContextSlot, 3); | 1044 __ CallRuntime(Runtime::kStoreContextSlot, 3); |
| 962 Apply(context, r0); | |
| 963 | 1045 |
| 964 } else if (var->slot() != NULL) { | 1046 } else if (var->slot() != NULL) { |
| 965 Slot* slot = var->slot(); | 1047 Slot* slot = var->slot(); |
| 966 switch (slot->type()) { | 1048 switch (slot->type()) { |
| 967 case Slot::LOCAL: | 1049 case Slot::LOCAL: |
| 968 case Slot::PARAMETER: | 1050 case Slot::PARAMETER: |
| 969 __ str(result_register(), MemOperand(fp, SlotOffset(slot))); | 1051 __ str(result_register(), MemOperand(fp, SlotOffset(slot))); |
| 970 break; | 1052 break; |
| 971 | 1053 |
| 972 case Slot::CONTEXT: { | 1054 case Slot::CONTEXT: { |
| 973 MemOperand target = EmitSlotSearch(slot, r1); | 1055 MemOperand target = EmitSlotSearch(slot, r1); |
| 974 __ str(result_register(), target); | 1056 __ str(result_register(), target); |
| 975 | 1057 |
| 976 // RecordWrite may destroy all its register arguments. | 1058 // RecordWrite may destroy all its register arguments. |
| 977 __ mov(r3, result_register()); | 1059 __ mov(r3, result_register()); |
| 978 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 1060 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 979 | 1061 |
| 980 __ mov(r2, Operand(offset)); | 1062 __ mov(r2, Operand(offset)); |
| 981 __ RecordWrite(r1, r2, r3); | 1063 __ RecordWrite(r1, r2, r3); |
| 982 break; | 1064 break; |
| 983 } | 1065 } |
| 984 | 1066 |
| 985 case Slot::LOOKUP: | 1067 case Slot::LOOKUP: |
| 986 UNREACHABLE(); | 1068 UNREACHABLE(); |
| 987 break; | 1069 break; |
| 988 } | 1070 } |
| 989 Apply(context, result_register()); | |
| 990 | 1071 |
| 991 } else { | 1072 } else { |
| 992 // Variables rewritten as properties are not treated as variables in | 1073 // Variables rewritten as properties are not treated as variables in |
| 993 // assignments. | 1074 // assignments. |
| 994 UNREACHABLE(); | 1075 UNREACHABLE(); |
| 995 } | 1076 } |
| 1077 Apply(context, result_register()); |
| 996 } | 1078 } |
| 997 | 1079 |
| 998 | 1080 |
| 999 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { | 1081 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { |
| 1000 // Assignment to a property, using a named store IC. | 1082 // Assignment to a property, using a named store IC. |
| 1001 Property* prop = expr->target()->AsProperty(); | 1083 Property* prop = expr->target()->AsProperty(); |
| 1002 ASSERT(prop != NULL); | 1084 ASSERT(prop != NULL); |
| 1003 ASSERT(prop->key()->AsLiteral() != NULL); | 1085 ASSERT(prop->key()->AsLiteral() != NULL); |
| 1004 | 1086 |
| 1005 // If the assignment starts a block of assignments to the same object, | 1087 // If the assignment starts a block of assignments to the same object, |
| 1006 // change to slow case to avoid the quadratic behavior of repeatedly | 1088 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1007 // adding fast properties. | 1089 // adding fast properties. |
| 1008 if (expr->starts_initialization_block()) { | 1090 if (expr->starts_initialization_block()) { |
| 1009 __ push(result_register()); | 1091 __ push(result_register()); |
| 1010 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value. | 1092 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is now under value. |
| 1011 __ push(ip); | 1093 __ push(ip); |
| 1012 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1094 __ CallRuntime(Runtime::kToSlowProperties, 1); |
| 1013 __ pop(result_register()); | 1095 __ pop(result_register()); |
| 1014 } | 1096 } |
| 1015 | 1097 |
| 1016 // Record source code position before IC call. | 1098 // Record source code position before IC call. |
| 1017 SetSourcePosition(expr->position()); | 1099 SetSourcePosition(expr->position()); |
| 1018 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1100 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
| 1101 if (expr->ends_initialization_block()) { |
| 1102 __ ldr(r1, MemOperand(sp)); |
| 1103 } else { |
| 1104 __ pop(r1); |
| 1105 } |
| 1106 |
| 1019 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1107 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1020 __ Call(ic, RelocInfo::CODE_TARGET); | 1108 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1021 | 1109 |
| 1022 // If the assignment ends an initialization block, revert to fast case. | 1110 // If the assignment ends an initialization block, revert to fast case. |
| 1023 if (expr->ends_initialization_block()) { | 1111 if (expr->ends_initialization_block()) { |
| 1024 __ push(r0); // Result of assignment, saved even if not needed. | 1112 __ push(r0); // Result of assignment, saved even if not needed. |
| 1025 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. | 1113 __ ldr(ip, MemOperand(sp, kPointerSize)); // Receiver is under value. |
| 1026 __ push(ip); | 1114 __ push(ip); |
| 1027 __ CallRuntime(Runtime::kToFastProperties, 1); | 1115 __ CallRuntime(Runtime::kToFastProperties, 1); |
| 1028 __ pop(r0); | 1116 __ pop(r0); |
| 1117 DropAndApply(1, context_, r0); |
| 1118 } else { |
| 1119 Apply(context_, r0); |
| 1029 } | 1120 } |
| 1030 | |
| 1031 DropAndApply(1, context_, r0); | |
| 1032 } | 1121 } |
| 1033 | 1122 |
| 1034 | 1123 |
| 1035 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1124 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 1036 // Assignment to a property, using a keyed store IC. | 1125 // Assignment to a property, using a keyed store IC. |
| 1037 | 1126 |
| 1038 // If the assignment starts a block of assignments to the same object, | 1127 // If the assignment starts a block of assignments to the same object, |
| 1039 // change to slow case to avoid the quadratic behavior of repeatedly | 1128 // change to slow case to avoid the quadratic behavior of repeatedly |
| 1040 // adding fast properties. | 1129 // adding fast properties. |
| 1041 if (expr->starts_initialization_block()) { | 1130 if (expr->starts_initialization_block()) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 DropAndApply(1, context_, r0); | 1169 DropAndApply(1, context_, r0); |
| 1081 } else { | 1170 } else { |
| 1082 VisitForValue(expr->key(), kStack); | 1171 VisitForValue(expr->key(), kStack); |
| 1083 EmitKeyedPropertyLoad(expr); | 1172 EmitKeyedPropertyLoad(expr); |
| 1084 // Drop key and receiver left on the stack by IC. | 1173 // Drop key and receiver left on the stack by IC. |
| 1085 DropAndApply(2, context_, r0); | 1174 DropAndApply(2, context_, r0); |
| 1086 } | 1175 } |
| 1087 } | 1176 } |
| 1088 | 1177 |
| 1089 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 1178 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 1090 Handle<Object> ignored, | 1179 Handle<Object> name, |
| 1091 RelocInfo::Mode mode) { | 1180 RelocInfo::Mode mode) { |
| 1092 // Code common for calls using the IC. | 1181 // Code common for calls using the IC. |
| 1093 ZoneList<Expression*>* args = expr->arguments(); | 1182 ZoneList<Expression*>* args = expr->arguments(); |
| 1094 int arg_count = args->length(); | 1183 int arg_count = args->length(); |
| 1095 for (int i = 0; i < arg_count; i++) { | 1184 for (int i = 0; i < arg_count; i++) { |
| 1096 VisitForValue(args->at(i), kStack); | 1185 VisitForValue(args->at(i), kStack); |
| 1097 } | 1186 } |
| 1187 __ mov(r2, Operand(name)); |
| 1098 // Record source position for debugger. | 1188 // Record source position for debugger. |
| 1099 SetSourcePosition(expr->position()); | 1189 SetSourcePosition(expr->position()); |
| 1100 // Call the IC initialization code. | 1190 // Call the IC initialization code. |
| 1101 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1191 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1102 NOT_IN_LOOP); | 1192 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
| 1103 __ Call(ic, mode); | 1193 __ Call(ic, mode); |
| 1104 // Restore context register. | 1194 // Restore context register. |
| 1105 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1195 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1106 // Discard the function left on TOS. | 1196 Apply(context_, r0); |
| 1107 DropAndApply(1, context_, r0); | |
| 1108 } | 1197 } |
| 1109 | 1198 |
| 1110 | 1199 |
| 1111 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 1200 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| 1112 // Code common for calls using the call stub. | 1201 // Code common for calls using the call stub. |
| 1113 ZoneList<Expression*>* args = expr->arguments(); | 1202 ZoneList<Expression*>* args = expr->arguments(); |
| 1114 int arg_count = args->length(); | 1203 int arg_count = args->length(); |
| 1115 for (int i = 0; i < arg_count; i++) { | 1204 for (int i = 0; i < arg_count; i++) { |
| 1116 VisitForValue(args->at(i), kStack); | 1205 VisitForValue(args->at(i), kStack); |
| 1117 } | 1206 } |
| 1118 // Record source position for debugger. | 1207 // Record source position for debugger. |
| 1119 SetSourcePosition(expr->position()); | 1208 SetSourcePosition(expr->position()); |
| 1120 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); | 1209 CallFunctionStub stub(arg_count, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
| 1121 __ CallStub(&stub); | 1210 __ CallStub(&stub); |
| 1122 // Restore context register. | 1211 // Restore context register. |
| 1123 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1212 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1124 // Discard the function left on TOS. | |
| 1125 DropAndApply(1, context_, r0); | 1213 DropAndApply(1, context_, r0); |
| 1126 } | 1214 } |
| 1127 | 1215 |
| 1128 | 1216 |
| 1129 void FullCodeGenerator::VisitCall(Call* expr) { | 1217 void FullCodeGenerator::VisitCall(Call* expr) { |
| 1130 Comment cmnt(masm_, "[ Call"); | 1218 Comment cmnt(masm_, "[ Call"); |
| 1131 Expression* fun = expr->expression(); | 1219 Expression* fun = expr->expression(); |
| 1132 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1220 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 1133 | 1221 |
| 1134 if (var != NULL && var->is_possibly_eval()) { | 1222 if (var != NULL && var->is_possibly_eval()) { |
| 1135 // Call to the identifier 'eval'. | 1223 // Call to the identifier 'eval'. |
| 1136 UNREACHABLE(); | 1224 UNREACHABLE(); |
| 1137 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1225 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 1138 // Call to a global variable. | 1226 // Push global object as receiver for the call IC. |
| 1139 __ mov(r1, Operand(var->name())); | |
| 1140 // Push global object as receiver for the call IC lookup. | |
| 1141 __ ldr(r0, CodeGenerator::GlobalObject()); | 1227 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 1142 __ stm(db_w, sp, r1.bit() | r0.bit()); | 1228 __ push(r0); |
| 1143 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 1229 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
| 1144 } else if (var != NULL && var->slot() != NULL && | 1230 } else if (var != NULL && var->slot() != NULL && |
| 1145 var->slot()->type() == Slot::LOOKUP) { | 1231 var->slot()->type() == Slot::LOOKUP) { |
| 1146 // Call to a lookup slot. | 1232 // Call to a lookup slot. |
| 1147 UNREACHABLE(); | 1233 UNREACHABLE(); |
| 1148 } else if (fun->AsProperty() != NULL) { | 1234 } else if (fun->AsProperty() != NULL) { |
| 1149 // Call to an object property. | 1235 // Call to an object property. |
| 1150 Property* prop = fun->AsProperty(); | 1236 Property* prop = fun->AsProperty(); |
| 1151 Literal* key = prop->key()->AsLiteral(); | 1237 Literal* key = prop->key()->AsLiteral(); |
| 1152 if (key != NULL && key->handle()->IsSymbol()) { | 1238 if (key != NULL && key->handle()->IsSymbol()) { |
| 1153 // Call to a named property, use call IC. | 1239 // Call to a named property, use call IC. |
| 1154 __ mov(r0, Operand(key->handle())); | |
| 1155 __ push(r0); | |
| 1156 VisitForValue(prop->obj(), kStack); | 1240 VisitForValue(prop->obj(), kStack); |
| 1157 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 1241 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 1158 } else { | 1242 } else { |
| 1159 // Call to a keyed property, use keyed load IC followed by function | 1243 // Call to a keyed property, use keyed load IC followed by function |
| 1160 // call. | 1244 // call. |
| 1161 VisitForValue(prop->obj(), kStack); | 1245 VisitForValue(prop->obj(), kStack); |
| 1162 VisitForValue(prop->key(), kStack); | 1246 VisitForValue(prop->key(), kStack); |
| 1163 // Record source code position for IC call. | 1247 // Record source code position for IC call. |
| 1164 SetSourcePosition(prop->position()); | 1248 SetSourcePosition(prop->position()); |
| 1165 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1249 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1231 DropAndApply(1, context_, r0); | 1315 DropAndApply(1, context_, r0); |
| 1232 } | 1316 } |
| 1233 | 1317 |
| 1234 | 1318 |
| 1235 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1319 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 1236 Comment cmnt(masm_, "[ CallRuntime"); | 1320 Comment cmnt(masm_, "[ CallRuntime"); |
| 1237 ZoneList<Expression*>* args = expr->arguments(); | 1321 ZoneList<Expression*>* args = expr->arguments(); |
| 1238 | 1322 |
| 1239 if (expr->is_jsruntime()) { | 1323 if (expr->is_jsruntime()) { |
| 1240 // Prepare for calling JS runtime function. | 1324 // Prepare for calling JS runtime function. |
| 1241 __ mov(r1, Operand(expr->name())); | |
| 1242 __ ldr(r0, CodeGenerator::GlobalObject()); | 1325 __ ldr(r0, CodeGenerator::GlobalObject()); |
| 1243 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); | 1326 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); |
| 1244 __ stm(db_w, sp, r1.bit() | r0.bit()); | 1327 __ push(r0); |
| 1245 } | 1328 } |
| 1246 | 1329 |
| 1247 // Push the arguments ("left-to-right"). | 1330 // Push the arguments ("left-to-right"). |
| 1248 int arg_count = args->length(); | 1331 int arg_count = args->length(); |
| 1249 for (int i = 0; i < arg_count; i++) { | 1332 for (int i = 0; i < arg_count; i++) { |
| 1250 VisitForValue(args->at(i), kStack); | 1333 VisitForValue(args->at(i), kStack); |
| 1251 } | 1334 } |
| 1252 | 1335 |
| 1253 if (expr->is_jsruntime()) { | 1336 if (expr->is_jsruntime()) { |
| 1254 // Call the JS runtime function. | 1337 // Call the JS runtime function. |
| 1338 __ mov(r2, Operand(expr->name())); |
| 1255 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1339 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 1256 NOT_IN_LOOP); | 1340 NOT_IN_LOOP); |
| 1257 __ Call(ic, RelocInfo::CODE_TARGET); | 1341 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1258 // Restore context register. | 1342 // Restore context register. |
| 1259 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1343 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 1260 // Discard the function left on TOS. | |
| 1261 DropAndApply(1, context_, r0); | |
| 1262 } else { | 1344 } else { |
| 1263 // Call the C runtime function. | 1345 // Call the C runtime function. |
| 1264 __ CallRuntime(expr->function(), arg_count); | 1346 __ CallRuntime(expr->function(), arg_count); |
| 1265 Apply(context_, r0); | |
| 1266 } | 1347 } |
| 1348 Apply(context_, r0); |
| 1267 } | 1349 } |
| 1268 | 1350 |
| 1269 | 1351 |
| 1270 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1352 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 1271 switch (expr->op()) { | 1353 switch (expr->op()) { |
| 1272 case Token::VOID: { | 1354 case Token::VOID: { |
| 1273 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1355 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
| 1274 VisitForEffect(expr->expression()); | 1356 VisitForEffect(expr->expression()); |
| 1275 switch (context_) { | 1357 switch (context_) { |
| 1276 case Expression::kUninitialized: | 1358 case Expression::kUninitialized: |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1541 if (context_ != Expression::kEffect) { | 1623 if (context_ != Expression::kEffect) { |
| 1542 ApplyTOS(context_); | 1624 ApplyTOS(context_); |
| 1543 } | 1625 } |
| 1544 } else { | 1626 } else { |
| 1545 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 1627 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1546 context_); | 1628 context_); |
| 1547 } | 1629 } |
| 1548 break; | 1630 break; |
| 1549 case NAMED_PROPERTY: { | 1631 case NAMED_PROPERTY: { |
| 1550 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); | 1632 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
| 1633 __ pop(r1); |
| 1551 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 1634 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
| 1552 __ Call(ic, RelocInfo::CODE_TARGET); | 1635 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1553 if (expr->is_postfix()) { | 1636 if (expr->is_postfix()) { |
| 1554 __ Drop(1); // Result is on the stack under the receiver. | |
| 1555 if (context_ != Expression::kEffect) { | 1637 if (context_ != Expression::kEffect) { |
| 1556 ApplyTOS(context_); | 1638 ApplyTOS(context_); |
| 1557 } | 1639 } |
| 1558 } else { | 1640 } else { |
| 1559 DropAndApply(1, context_, r0); | 1641 Apply(context_, r0); |
| 1560 } | 1642 } |
| 1561 break; | 1643 break; |
| 1562 } | 1644 } |
| 1563 case KEYED_PROPERTY: { | 1645 case KEYED_PROPERTY: { |
| 1564 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1646 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
| 1565 __ Call(ic, RelocInfo::CODE_TARGET); | 1647 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1566 if (expr->is_postfix()) { | 1648 if (expr->is_postfix()) { |
| 1567 __ Drop(2); // Result is on the stack under the key and the receiver. | 1649 __ Drop(2); // Result is on the stack under the key and the receiver. |
| 1568 if (context_ != Expression::kEffect) { | 1650 if (context_ != Expression::kEffect) { |
| 1569 ApplyTOS(context_); | 1651 ApplyTOS(context_); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1774 __ pop(result_register()); | 1856 __ pop(result_register()); |
| 1775 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1857 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
| 1776 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 1858 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 1777 __ add(pc, r1, Operand(masm_->CodeObject())); | 1859 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 1778 } | 1860 } |
| 1779 | 1861 |
| 1780 | 1862 |
| 1781 #undef __ | 1863 #undef __ |
| 1782 | 1864 |
| 1783 } } // namespace v8::internal | 1865 } } // namespace v8::internal |
| OLD | NEW |