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 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1059 // By emitting a nop we make sure that we do not have a "test eax,..." | 1059 // By emitting a nop we make sure that we do not have a "test eax,..." |
1060 // instruction after the call it is treated specially by the LoadIC code. | 1060 // instruction after the call it is treated specially by the LoadIC code. |
1061 __ nop(); | 1061 __ nop(); |
1062 // Drop key left on the stack by IC. | 1062 // Drop key left on the stack by IC. |
1063 __ add(Operand(esp), Immediate(kPointerSize)); | 1063 __ add(Operand(esp), Immediate(kPointerSize)); |
1064 } | 1064 } |
1065 DropAndMove(expr->context(), eax); | 1065 DropAndMove(expr->context(), eax); |
1066 } | 1066 } |
1067 | 1067 |
1068 | 1068 |
1069 void FastCodeGenerator::EmitCallWithIC(Call* expr, RelocInfo::Mode reloc_info) { | 1069 void FastCodeGenerator::EmitCallWithIC(Call* expr, |
| 1070 Handle<Object> name, |
| 1071 RelocInfo::Mode mode) { |
1070 // Code common for calls using the IC. | 1072 // Code common for calls using the IC. |
1071 ZoneList<Expression*>* args = expr->arguments(); | 1073 ZoneList<Expression*>* args = expr->arguments(); |
1072 int arg_count = args->length(); | 1074 int arg_count = args->length(); |
1073 for (int i = 0; i < arg_count; i++) { | 1075 for (int i = 0; i < arg_count; i++) { |
1074 Visit(args->at(i)); | 1076 Visit(args->at(i)); |
1075 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 1077 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
1076 } | 1078 } |
1077 // Record source position for debugger. | 1079 __ Set(ecx, Immediate(name)); |
| 1080 // Record source position of the IC call. |
1078 SetSourcePosition(expr->position()); | 1081 SetSourcePosition(expr->position()); |
1079 // Call the IC initialization code. | 1082 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1080 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1083 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
1081 NOT_IN_LOOP); | 1084 __ call(ic, mode); |
1082 __ call(ic, reloc_info); | |
1083 // Restore context register. | 1085 // Restore context register. |
1084 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1086 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1085 // Discard the function left on TOS. | 1087 Move(expr->context(), eax); |
1086 DropAndMove(expr->context(), eax); | |
1087 } | 1088 } |
1088 | 1089 |
1089 | 1090 |
1090 void FastCodeGenerator::EmitCallWithStub(Call* expr) { | 1091 void FastCodeGenerator::EmitCallWithStub(Call* expr) { |
1091 // Code common for calls using the call stub. | 1092 // Code common for calls using the call stub. |
1092 ZoneList<Expression*>* args = expr->arguments(); | 1093 ZoneList<Expression*>* args = expr->arguments(); |
1093 int arg_count = args->length(); | 1094 int arg_count = args->length(); |
1094 for (int i = 0; i < arg_count; i++) { | 1095 for (int i = 0; i < arg_count; i++) { |
1095 Visit(args->at(i)); | 1096 Visit(args->at(i)); |
1096 } | 1097 } |
1097 // Record source position for debugger. | 1098 // Record source position for debugger. |
1098 SetSourcePosition(expr->position()); | 1099 SetSourcePosition(expr->position()); |
1099 CallFunctionStub stub(arg_count, NOT_IN_LOOP); | 1100 CallFunctionStub stub(arg_count, NOT_IN_LOOP); |
1100 __ CallStub(&stub); | 1101 __ CallStub(&stub); |
1101 // Restore context register. | 1102 // Restore context register. |
1102 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1103 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1103 // Discard the function left on TOS. | |
1104 DropAndMove(expr->context(), eax); | 1104 DropAndMove(expr->context(), eax); |
1105 } | 1105 } |
1106 | 1106 |
1107 | 1107 |
1108 void FastCodeGenerator::VisitCall(Call* expr) { | 1108 void FastCodeGenerator::VisitCall(Call* expr) { |
1109 Comment cmnt(masm_, "[ Call"); | 1109 Comment cmnt(masm_, "[ Call"); |
1110 Expression* fun = expr->expression(); | 1110 Expression* fun = expr->expression(); |
1111 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1111 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1112 | 1112 |
1113 if (var != NULL && var->is_possibly_eval()) { | 1113 if (var != NULL && var->is_possibly_eval()) { |
1114 // Call to the identifier 'eval'. | 1114 // Call to the identifier 'eval'. |
1115 UNREACHABLE(); | 1115 UNREACHABLE(); |
1116 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1116 } else if (var != NULL && !var->is_this() && var->is_global()) { |
1117 // Call to a global variable. | 1117 // Push global object as receiver for the call IC. |
1118 __ push(Immediate(var->name())); | |
1119 // Push global object as receiver for the call IC lookup. | |
1120 __ push(CodeGenerator::GlobalObject()); | 1118 __ push(CodeGenerator::GlobalObject()); |
1121 EmitCallWithIC(expr, RelocInfo::CODE_TARGET_CONTEXT); | 1119 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
1122 } else if (var != NULL && var->slot() != NULL && | 1120 } else if (var != NULL && var->slot() != NULL && |
1123 var->slot()->type() == Slot::LOOKUP) { | 1121 var->slot()->type() == Slot::LOOKUP) { |
1124 // Call to a lookup slot. | 1122 // Call to a lookup slot. |
1125 UNREACHABLE(); | 1123 UNREACHABLE(); |
1126 } else if (fun->AsProperty() != NULL) { | 1124 } else if (fun->AsProperty() != NULL) { |
1127 // Call to an object property. | 1125 // Call to an object property. |
1128 Property* prop = fun->AsProperty(); | 1126 Property* prop = fun->AsProperty(); |
1129 Literal* key = prop->key()->AsLiteral(); | 1127 Literal* key = prop->key()->AsLiteral(); |
1130 if (key != NULL && key->handle()->IsSymbol()) { | 1128 if (key != NULL && key->handle()->IsSymbol()) { |
1131 // Call to a named property, use call IC. | 1129 // Call to a named property, use call IC. |
1132 __ push(Immediate(key->handle())); | |
1133 Visit(prop->obj()); | 1130 Visit(prop->obj()); |
1134 EmitCallWithIC(expr, RelocInfo::CODE_TARGET); | 1131 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
1135 } else { | 1132 } else { |
1136 // Call to a keyed property, use keyed load IC followed by function | 1133 // Call to a keyed property, use keyed load IC followed by function |
1137 // call. | 1134 // call. |
1138 Visit(prop->obj()); | 1135 Visit(prop->obj()); |
1139 Visit(prop->key()); | 1136 Visit(prop->key()); |
1140 // Record source code position for IC call. | 1137 // Record source code position for IC call. |
1141 SetSourcePosition(prop->position()); | 1138 SetSourcePosition(prop->position()); |
1142 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1139 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1143 __ call(ic, RelocInfo::CODE_TARGET); | 1140 __ call(ic, RelocInfo::CODE_TARGET); |
1144 // By emitting a nop we make sure that we do not have a "test eax,..." | 1141 // By emitting a nop we make sure that we do not have a "test eax,..." |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 DropAndMove(expr->context(), eax); | 1213 DropAndMove(expr->context(), eax); |
1217 } | 1214 } |
1218 | 1215 |
1219 | 1216 |
1220 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1217 void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1221 Comment cmnt(masm_, "[ CallRuntime"); | 1218 Comment cmnt(masm_, "[ CallRuntime"); |
1222 ZoneList<Expression*>* args = expr->arguments(); | 1219 ZoneList<Expression*>* args = expr->arguments(); |
1223 | 1220 |
1224 if (expr->is_jsruntime()) { | 1221 if (expr->is_jsruntime()) { |
1225 // Prepare for calling JS runtime function. | 1222 // Prepare for calling JS runtime function. |
1226 __ push(Immediate(expr->name())); | |
1227 __ mov(eax, CodeGenerator::GlobalObject()); | 1223 __ mov(eax, CodeGenerator::GlobalObject()); |
1228 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); | 1224 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); |
1229 } | 1225 } |
1230 | 1226 |
1231 // Push the arguments ("left-to-right"). | 1227 // Push the arguments ("left-to-right"). |
1232 int arg_count = args->length(); | 1228 int arg_count = args->length(); |
1233 for (int i = 0; i < arg_count; i++) { | 1229 for (int i = 0; i < arg_count; i++) { |
1234 Visit(args->at(i)); | 1230 Visit(args->at(i)); |
1235 ASSERT_EQ(Expression::kValue, args->at(i)->context()); | 1231 ASSERT_EQ(Expression::kValue, args->at(i)->context()); |
1236 } | 1232 } |
1237 | 1233 |
1238 if (expr->is_jsruntime()) { | 1234 if (expr->is_jsruntime()) { |
1239 // Call the JS runtime function. | 1235 // Call the JS runtime function via a call IC. |
1240 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1236 __ Set(ecx, Immediate(expr->name())); |
1241 NOT_IN_LOOP); | 1237 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1238 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
1242 __ call(ic, RelocInfo::CODE_TARGET); | 1239 __ call(ic, RelocInfo::CODE_TARGET); |
1243 // Restore context register. | 1240 // Restore context register. |
1244 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 1241 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
1245 // Discard the function left on TOS. | |
1246 DropAndMove(expr->context(), eax); | |
1247 } else { | 1242 } else { |
1248 // Call the C runtime function. | 1243 // Call the C runtime function. |
1249 __ CallRuntime(expr->function(), arg_count); | 1244 __ CallRuntime(expr->function(), arg_count); |
1250 Move(expr->context(), eax); | |
1251 } | 1245 } |
| 1246 Move(expr->context(), eax); |
1252 } | 1247 } |
1253 | 1248 |
1254 | 1249 |
1255 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1250 void FastCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1256 switch (expr->op()) { | 1251 switch (expr->op()) { |
1257 case Token::VOID: { | 1252 case Token::VOID: { |
1258 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1253 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
1259 Visit(expr->expression()); | 1254 Visit(expr->expression()); |
1260 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); | 1255 ASSERT_EQ(Expression::kEffect, expr->expression()->context()); |
1261 switch (expr->context()) { | 1256 switch (expr->context()) { |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1712 | 1707 |
1713 | 1708 |
1714 void FastCodeGenerator::ThrowException() { | 1709 void FastCodeGenerator::ThrowException() { |
1715 __ push(result_register()); | 1710 __ push(result_register()); |
1716 __ CallRuntime(Runtime::kThrow, 1); | 1711 __ CallRuntime(Runtime::kThrow, 1); |
1717 } | 1712 } |
1718 | 1713 |
1719 #undef __ | 1714 #undef __ |
1720 | 1715 |
1721 } } // namespace v8::internal | 1716 } } // namespace v8::internal |
OLD | NEW |