| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 } | 1008 } |
| 1009 | 1009 |
| 1010 if (result_saved) { | 1010 if (result_saved) { |
| 1011 ApplyTOS(context_); | 1011 ApplyTOS(context_); |
| 1012 } else { | 1012 } else { |
| 1013 Apply(context_, rax); | 1013 Apply(context_, rax); |
| 1014 } | 1014 } |
| 1015 } | 1015 } |
| 1016 | 1016 |
| 1017 | 1017 |
| 1018 void FullCodeGenerator::VisitAssignment(Assignment* expr) { |
| 1019 Comment cmnt(masm_, "[ Assignment"); |
| 1020 ASSERT(expr->op() != Token::INIT_CONST); |
| 1021 // Left-hand side can only be a property, a global or a (parameter or local) |
| 1022 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 1023 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1024 LhsKind assign_type = VARIABLE; |
| 1025 Property* prop = expr->target()->AsProperty(); |
| 1026 if (prop != NULL) { |
| 1027 assign_type = |
| 1028 (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; |
| 1029 } |
| 1030 |
| 1031 // Evaluate LHS expression. |
| 1032 switch (assign_type) { |
| 1033 case VARIABLE: |
| 1034 // Nothing to do here. |
| 1035 break; |
| 1036 case NAMED_PROPERTY: |
| 1037 if (expr->is_compound()) { |
| 1038 // We need the receiver both on the stack and in the accumulator. |
| 1039 VisitForValue(prop->obj(), kAccumulator); |
| 1040 __ push(result_register()); |
| 1041 } else { |
| 1042 VisitForValue(prop->obj(), kStack); |
| 1043 } |
| 1044 break; |
| 1045 case KEYED_PROPERTY: |
| 1046 VisitForValue(prop->obj(), kStack); |
| 1047 VisitForValue(prop->key(), kStack); |
| 1048 break; |
| 1049 } |
| 1050 |
| 1051 // If we have a compound assignment: Get value of LHS expression and |
| 1052 // store in on top of the stack. |
| 1053 if (expr->is_compound()) { |
| 1054 Location saved_location = location_; |
| 1055 location_ = kStack; |
| 1056 switch (assign_type) { |
| 1057 case VARIABLE: |
| 1058 EmitVariableLoad(expr->target()->AsVariableProxy()->var(), |
| 1059 Expression::kValue); |
| 1060 break; |
| 1061 case NAMED_PROPERTY: |
| 1062 EmitNamedPropertyLoad(prop); |
| 1063 __ push(result_register()); |
| 1064 break; |
| 1065 case KEYED_PROPERTY: |
| 1066 EmitKeyedPropertyLoad(prop); |
| 1067 __ push(result_register()); |
| 1068 break; |
| 1069 } |
| 1070 location_ = saved_location; |
| 1071 } |
| 1072 |
| 1073 // Evaluate RHS expression. |
| 1074 Expression* rhs = expr->value(); |
| 1075 VisitForValue(rhs, kAccumulator); |
| 1076 |
| 1077 // If we have a compound assignment: Apply operator. |
| 1078 if (expr->is_compound()) { |
| 1079 Location saved_location = location_; |
| 1080 location_ = kAccumulator; |
| 1081 EmitBinaryOp(expr->binary_op(), Expression::kValue); |
| 1082 location_ = saved_location; |
| 1083 } |
| 1084 |
| 1085 // Record source position before possible IC call. |
| 1086 SetSourcePosition(expr->position()); |
| 1087 |
| 1088 // Store the value. |
| 1089 switch (assign_type) { |
| 1090 case VARIABLE: |
| 1091 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), |
| 1092 context_); |
| 1093 break; |
| 1094 case NAMED_PROPERTY: |
| 1095 EmitNamedPropertyAssignment(expr); |
| 1096 break; |
| 1097 case KEYED_PROPERTY: |
| 1098 EmitKeyedPropertyAssignment(expr); |
| 1099 break; |
| 1100 } |
| 1101 } |
| 1102 |
| 1103 |
| 1018 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 1104 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
| 1019 SetSourcePosition(prop->position()); | 1105 SetSourcePosition(prop->position()); |
| 1020 Literal* key = prop->key()->AsLiteral(); | 1106 Literal* key = prop->key()->AsLiteral(); |
| 1021 __ Move(rcx, key->handle()); | 1107 __ Move(rcx, key->handle()); |
| 1022 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 1108 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
| 1023 __ Call(ic, RelocInfo::CODE_TARGET); | 1109 __ Call(ic, RelocInfo::CODE_TARGET); |
| 1024 __ nop(); | 1110 __ nop(); |
| 1025 } | 1111 } |
| 1026 | 1112 |
| 1027 | 1113 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 } else { | 1279 } else { |
| 1194 VisitForValue(expr->key(), kStack); | 1280 VisitForValue(expr->key(), kStack); |
| 1195 EmitKeyedPropertyLoad(expr); | 1281 EmitKeyedPropertyLoad(expr); |
| 1196 // Drop key and receiver left on the stack by IC. | 1282 // Drop key and receiver left on the stack by IC. |
| 1197 DropAndApply(2, context_, rax); | 1283 DropAndApply(2, context_, rax); |
| 1198 } | 1284 } |
| 1199 } | 1285 } |
| 1200 | 1286 |
| 1201 | 1287 |
| 1202 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 1288 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
| 1203 Handle<Object> ignored, | 1289 Handle<Object> name, |
| 1204 RelocInfo::Mode mode) { | 1290 RelocInfo::Mode mode) { |
| 1205 // Code common for calls using the IC. | 1291 // Code common for calls using the IC. |
| 1206 ZoneList<Expression*>* args = expr->arguments(); | 1292 ZoneList<Expression*>* args = expr->arguments(); |
| 1207 int arg_count = args->length(); | 1293 int arg_count = args->length(); |
| 1208 for (int i = 0; i < arg_count; i++) { | 1294 for (int i = 0; i < arg_count; i++) { |
| 1209 VisitForValue(args->at(i), kStack); | 1295 VisitForValue(args->at(i), kStack); |
| 1210 } | 1296 } |
| 1297 __ Move(rcx, name); |
| 1211 // Record source position for debugger. | 1298 // Record source position for debugger. |
| 1212 SetSourcePosition(expr->position()); | 1299 SetSourcePosition(expr->position()); |
| 1213 // Call the IC initialization code. | 1300 // Call the IC initialization code. |
| 1214 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1301 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1215 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1302 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
| 1216 in_loop); | 1303 in_loop); |
| 1217 __ Call(ic, mode); | 1304 __ Call(ic, mode); |
| 1218 // Restore context register. | 1305 // Restore context register. |
| 1219 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1306 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1220 // Discard the function left on TOS. | 1307 Apply(context_, rax); |
| 1221 DropAndApply(1, context_, rax); | |
| 1222 } | 1308 } |
| 1223 | 1309 |
| 1224 | 1310 |
| 1225 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 1311 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
| 1226 // Code common for calls using the call stub. | 1312 // Code common for calls using the call stub. |
| 1227 ZoneList<Expression*>* args = expr->arguments(); | 1313 ZoneList<Expression*>* args = expr->arguments(); |
| 1228 int arg_count = args->length(); | 1314 int arg_count = args->length(); |
| 1229 for (int i = 0; i < arg_count; i++) { | 1315 for (int i = 0; i < arg_count; i++) { |
| 1230 VisitForValue(args->at(i), kStack); | 1316 VisitForValue(args->at(i), kStack); |
| 1231 } | 1317 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1243 void FullCodeGenerator::VisitCall(Call* expr) { | 1329 void FullCodeGenerator::VisitCall(Call* expr) { |
| 1244 Comment cmnt(masm_, "[ Call"); | 1330 Comment cmnt(masm_, "[ Call"); |
| 1245 Expression* fun = expr->expression(); | 1331 Expression* fun = expr->expression(); |
| 1246 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1332 Variable* var = fun->AsVariableProxy()->AsVariable(); |
| 1247 | 1333 |
| 1248 if (var != NULL && var->is_possibly_eval()) { | 1334 if (var != NULL && var->is_possibly_eval()) { |
| 1249 // Call to the identifier 'eval'. | 1335 // Call to the identifier 'eval'. |
| 1250 UNREACHABLE(); | 1336 UNREACHABLE(); |
| 1251 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1337 } else if (var != NULL && !var->is_this() && var->is_global()) { |
| 1252 // Call to a global variable. | 1338 // Call to a global variable. |
| 1253 __ Push(var->name()); | |
| 1254 // Push global object as receiver for the call IC lookup. | 1339 // Push global object as receiver for the call IC lookup. |
| 1255 __ push(CodeGenerator::GlobalObject()); | 1340 __ push(CodeGenerator::GlobalObject()); |
| 1256 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 1341 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
| 1257 } else if (var != NULL && var->slot() != NULL && | 1342 } else if (var != NULL && var->slot() != NULL && |
| 1258 var->slot()->type() == Slot::LOOKUP) { | 1343 var->slot()->type() == Slot::LOOKUP) { |
| 1259 // Call to a lookup slot. | 1344 // Call to a lookup slot. |
| 1260 UNREACHABLE(); | 1345 UNREACHABLE(); |
| 1261 } else if (fun->AsProperty() != NULL) { | 1346 } else if (fun->AsProperty() != NULL) { |
| 1262 // Call to an object property. | 1347 // Call to an object property. |
| 1263 Property* prop = fun->AsProperty(); | 1348 Property* prop = fun->AsProperty(); |
| 1264 Literal* key = prop->key()->AsLiteral(); | 1349 Literal* key = prop->key()->AsLiteral(); |
| 1265 if (key != NULL && key->handle()->IsSymbol()) { | 1350 if (key != NULL && key->handle()->IsSymbol()) { |
| 1266 // Call to a named property, use call IC. | 1351 // Call to a named property, use call IC. |
| 1267 __ Push(key->handle()); | |
| 1268 VisitForValue(prop->obj(), kStack); | 1352 VisitForValue(prop->obj(), kStack); |
| 1269 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 1353 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
| 1270 } else { | 1354 } else { |
| 1271 // Call to a keyed property, use keyed load IC followed by function | 1355 // Call to a keyed property, use keyed load IC followed by function |
| 1272 // call. | 1356 // call. |
| 1273 VisitForValue(prop->obj(), kStack); | 1357 VisitForValue(prop->obj(), kStack); |
| 1274 VisitForValue(prop->key(), kStack); | 1358 VisitForValue(prop->key(), kStack); |
| 1275 // Record source code position for IC call. | 1359 // Record source code position for IC call. |
| 1276 SetSourcePosition(prop->position()); | 1360 SetSourcePosition(prop->position()); |
| 1277 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1361 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 DropAndApply(1, context_, rax); | 1432 DropAndApply(1, context_, rax); |
| 1349 } | 1433 } |
| 1350 | 1434 |
| 1351 | 1435 |
| 1352 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1436 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 1353 Comment cmnt(masm_, "[ CallRuntime"); | 1437 Comment cmnt(masm_, "[ CallRuntime"); |
| 1354 ZoneList<Expression*>* args = expr->arguments(); | 1438 ZoneList<Expression*>* args = expr->arguments(); |
| 1355 | 1439 |
| 1356 if (expr->is_jsruntime()) { | 1440 if (expr->is_jsruntime()) { |
| 1357 // Prepare for calling JS runtime function. | 1441 // Prepare for calling JS runtime function. |
| 1358 __ Push(expr->name()); | |
| 1359 __ movq(rax, CodeGenerator::GlobalObject()); | 1442 __ movq(rax, CodeGenerator::GlobalObject()); |
| 1360 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); | 1443 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); |
| 1361 } | 1444 } |
| 1362 | 1445 |
| 1363 // Push the arguments ("left-to-right"). | 1446 // Push the arguments ("left-to-right"). |
| 1364 int arg_count = args->length(); | 1447 int arg_count = args->length(); |
| 1365 for (int i = 0; i < arg_count; i++) { | 1448 for (int i = 0; i < arg_count; i++) { |
| 1366 VisitForValue(args->at(i), kStack); | 1449 VisitForValue(args->at(i), kStack); |
| 1367 } | 1450 } |
| 1368 | 1451 |
| 1369 if (expr->is_jsruntime()) { | 1452 if (expr->is_jsruntime()) { |
| 1370 // Call the JS runtime function. | 1453 // Call the JS runtime function using a call IC. |
| 1371 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1454 __ Move(rcx, expr->name()); |
| 1372 NOT_IN_LOOP); | 1455 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
| 1456 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, in_loop); |
| 1373 __ call(ic, RelocInfo::CODE_TARGET); | 1457 __ call(ic, RelocInfo::CODE_TARGET); |
| 1374 // Restore context register. | 1458 // Restore context register. |
| 1375 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1459 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 1376 // Discard the function left on TOS. | |
| 1377 DropAndApply(1, context_, rax); | |
| 1378 } else { | 1460 } else { |
| 1379 __ CallRuntime(expr->function(), arg_count); | 1461 __ CallRuntime(expr->function(), arg_count); |
| 1380 Apply(context_, rax); | |
| 1381 } | 1462 } |
| 1463 Apply(context_, rax); |
| 1382 } | 1464 } |
| 1383 | 1465 |
| 1384 | 1466 |
| 1385 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1467 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 1386 switch (expr->op()) { | 1468 switch (expr->op()) { |
| 1387 case Token::VOID: { | 1469 case Token::VOID: { |
| 1388 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); | 1470 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); |
| 1389 VisitForEffect(expr->expression()); | 1471 VisitForEffect(expr->expression()); |
| 1390 switch (context_) { | 1472 switch (context_) { |
| 1391 case Expression::kUninitialized: | 1473 case Expression::kUninitialized: |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1900 __ movq(Operand(rsp, 0), rdx); | 1982 __ movq(Operand(rsp, 0), rdx); |
| 1901 // And return. | 1983 // And return. |
| 1902 __ ret(0); | 1984 __ ret(0); |
| 1903 } | 1985 } |
| 1904 | 1986 |
| 1905 | 1987 |
| 1906 #undef __ | 1988 #undef __ |
| 1907 | 1989 |
| 1908 | 1990 |
| 1909 } } // namespace v8::internal | 1991 } } // namespace v8::internal |
| OLD | NEW |