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 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 __ push(source); | 240 __ push(source); |
241 TestAndBranch(source, &discard, false_label_); | 241 TestAndBranch(source, &discard, false_label_); |
242 __ bind(&discard); | 242 __ bind(&discard); |
243 __ pop(); | 243 __ pop(); |
244 __ jmp(true_label_); | 244 __ jmp(true_label_); |
245 } | 245 } |
246 } | 246 } |
247 } | 247 } |
248 | 248 |
249 | 249 |
| 250 void FastCodeGenerator::MoveTOS(Expression::Context context) { |
| 251 switch (context) { |
| 252 case Expression::kUninitialized: |
| 253 UNREACHABLE(); |
| 254 case Expression::kEffect: |
| 255 __ Drop(1); |
| 256 break; |
| 257 case Expression::kValue: |
| 258 break; |
| 259 case Expression::kTest: |
| 260 __ pop(r0); |
| 261 TestAndBranch(r0, true_label_, false_label_); |
| 262 break; |
| 263 case Expression::kValueTest: { |
| 264 Label discard; |
| 265 __ ldr(r0, MemOperand(sp, 0)); |
| 266 TestAndBranch(r0, true_label_, &discard); |
| 267 __ bind(&discard); |
| 268 __ Drop(1); |
| 269 __ jmp(false_label_); |
| 270 break; |
| 271 } |
| 272 case Expression::kTestValue: { |
| 273 Label discard; |
| 274 __ ldr(r0, MemOperand(sp, 0)); |
| 275 TestAndBranch(r0, &discard, false_label_); |
| 276 __ bind(&discard); |
| 277 __ Drop(1); |
| 278 __ jmp(true_label_); |
| 279 } |
| 280 } |
| 281 } |
| 282 |
| 283 |
250 template <> | 284 template <> |
251 MemOperand FastCodeGenerator::CreateSlotOperand<MemOperand>( | 285 MemOperand FastCodeGenerator::CreateSlotOperand<MemOperand>( |
252 Slot* source, | 286 Slot* source, |
253 Register scratch) { | 287 Register scratch) { |
254 switch (source->type()) { | 288 switch (source->type()) { |
255 case Slot::PARAMETER: | 289 case Slot::PARAMETER: |
256 case Slot::LOCAL: | 290 case Slot::LOCAL: |
257 return MemOperand(fp, SlotOffset(source)); | 291 return MemOperand(fp, SlotOffset(source)); |
258 case Slot::CONTEXT: { | 292 case Slot::CONTEXT: { |
259 int context_chain_length = | 293 int context_chain_length = |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 __ pop(); | 866 __ pop(); |
833 __ jmp(true_label_); | 867 __ jmp(true_label_); |
834 break; | 868 break; |
835 } | 869 } |
836 } | 870 } |
837 } | 871 } |
838 | 872 |
839 | 873 |
840 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, | 874 void FastCodeGenerator::EmitNamedPropertyLoad(Property* prop, |
841 Expression::Context context) { | 875 Expression::Context context) { |
| 876 SetSourcePosition(prop->position()); |
842 Literal* key = prop->key()->AsLiteral(); | 877 Literal* key = prop->key()->AsLiteral(); |
843 __ mov(r2, Operand(key->handle())); | 878 __ mov(r2, Operand(key->handle())); |
844 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 879 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); |
845 __ Call(ic, RelocInfo::CODE_TARGET); | 880 __ Call(ic, RelocInfo::CODE_TARGET); |
846 Move(context, r0); | 881 Move(context, r0); |
847 } | 882 } |
848 | 883 |
849 | 884 |
850 void FastCodeGenerator::EmitKeyedPropertyLoad(Expression::Context context) { | 885 void FastCodeGenerator::EmitKeyedPropertyLoad(Property* prop, |
| 886 Expression::Context context) { |
| 887 SetSourcePosition(prop->position()); |
851 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 888 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
852 __ Call(ic, RelocInfo::CODE_TARGET); | 889 __ Call(ic, RelocInfo::CODE_TARGET); |
853 Move(context, r0); | 890 Move(context, r0); |
854 } | 891 } |
855 | 892 |
856 | 893 |
857 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, | 894 void FastCodeGenerator::EmitCompoundAssignmentOp(Token::Value op, |
858 Expression::Context context) { | 895 Expression::Context context) { |
859 __ pop(r0); | 896 __ pop(r0); |
860 __ pop(r1); | 897 __ pop(r1); |
861 GenericBinaryOpStub stub(op, | 898 GenericBinaryOpStub stub(op, |
862 NO_OVERWRITE); | 899 NO_OVERWRITE); |
863 __ CallStub(&stub); | 900 __ CallStub(&stub); |
864 Move(context, r0); | 901 Move(context, r0); |
865 } | 902 } |
866 | 903 |
867 | 904 |
868 void FastCodeGenerator::EmitVariableAssignment(Assignment* expr) { | 905 void FastCodeGenerator::EmitVariableAssignment(Variable* var, |
869 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | 906 Expression::Context context) { |
870 ASSERT(var != NULL); | 907 ASSERT(var != NULL); |
871 ASSERT(var->is_global() || var->slot() != NULL); | 908 ASSERT(var->is_global() || var->slot() != NULL); |
872 if (var->is_global()) { | 909 if (var->is_global()) { |
873 // Assignment to a global variable. Use inline caching for the | 910 // Assignment to a global variable. Use inline caching for the |
874 // assignment. Right-hand-side value is passed in r0, variable name in | 911 // assignment. Right-hand-side value is passed in r0, variable name in |
875 // r2, and the global object on the stack. | 912 // r2, and the global object on the stack. |
876 __ pop(r0); | 913 __ pop(r0); |
877 __ mov(r2, Operand(var->name())); | 914 __ mov(r2, Operand(var->name())); |
878 __ ldr(ip, CodeGenerator::GlobalObject()); | 915 __ ldr(ip, CodeGenerator::GlobalObject()); |
879 __ push(ip); | 916 __ push(ip); |
880 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | 917 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
881 __ Call(ic, RelocInfo::CODE_TARGET); | 918 __ Call(ic, RelocInfo::CODE_TARGET); |
882 // Overwrite the global object on the stack with the result if needed. | 919 // Overwrite the global object on the stack with the result if needed. |
883 DropAndMove(expr->context(), r0); | 920 DropAndMove(context, r0); |
884 | 921 |
885 } else if (var->slot()) { | 922 } else if (var->slot()) { |
886 Slot* slot = var->slot(); | 923 Slot* slot = var->slot(); |
887 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled. | 924 ASSERT_NOT_NULL(slot); // Variables rewritten as properties not handled. |
888 switch (slot->type()) { | 925 switch (slot->type()) { |
889 case Slot::LOCAL: | 926 case Slot::LOCAL: |
890 case Slot::PARAMETER: { | 927 case Slot::PARAMETER: { |
891 switch (expr->context()) { | 928 switch (context) { |
892 case Expression::kUninitialized: | 929 case Expression::kUninitialized: |
893 UNREACHABLE(); | 930 UNREACHABLE(); |
894 case Expression::kEffect: | 931 case Expression::kEffect: |
895 // Perform assignment and discard value. | 932 // Perform assignment and discard value. |
896 __ pop(r0); | 933 __ pop(r0); |
897 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); | 934 __ str(r0, MemOperand(fp, SlotOffset(var->slot()))); |
898 break; | 935 break; |
899 case Expression::kValue: | 936 case Expression::kValue: |
900 // Perform assignment and preserve value. | 937 // Perform assignment and preserve value. |
901 __ ldr(r0, MemOperand(sp)); | 938 __ ldr(r0, MemOperand(sp)); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
946 } | 983 } |
947 } else { // Slot is in the current context. Generate optimized code. | 984 } else { // Slot is in the current context. Generate optimized code. |
948 __ mov(r0, cp); | 985 __ mov(r0, cp); |
949 } | 986 } |
950 // The context may be an intermediate context, not a function context. | 987 // The context may be an intermediate context, not a function context. |
951 __ ldr(r0, CodeGenerator::ContextOperand(r0, Context::FCONTEXT_INDEX)); | 988 __ ldr(r0, CodeGenerator::ContextOperand(r0, Context::FCONTEXT_INDEX)); |
952 __ pop(r1); | 989 __ pop(r1); |
953 __ str(r1, CodeGenerator::ContextOperand(r0, slot->index())); | 990 __ str(r1, CodeGenerator::ContextOperand(r0, slot->index())); |
954 | 991 |
955 // RecordWrite may destroy all its register arguments. | 992 // RecordWrite may destroy all its register arguments. |
956 if (expr->context() == Expression::kValue) { | 993 if (context == Expression::kValue) { |
957 __ push(r1); | 994 __ push(r1); |
958 } else if (expr->context() != Expression::kEffect) { | 995 } else if (context != Expression::kEffect) { |
959 __ mov(r3, r1); | 996 __ mov(r3, r1); |
960 } | 997 } |
961 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 998 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
962 | 999 |
963 // Update the write barrier for the array store with r0 as the scratch | 1000 // Update the write barrier for the array store with r0 as the scratch |
964 // register. Skip the write barrier if the value written (r1) is a smi. | 1001 // register. Skip the write barrier if the value written (r1) is a smi. |
965 // The smi test is part of RecordWrite on other platforms, not on arm. | 1002 // The smi test is part of RecordWrite on other platforms, not on arm. |
966 Label exit; | 1003 Label exit; |
967 __ tst(r1, Operand(kSmiTagMask)); | 1004 __ tst(r1, Operand(kSmiTagMask)); |
968 __ b(eq, &exit); | 1005 __ b(eq, &exit); |
969 | 1006 |
970 __ mov(r2, Operand(offset)); | 1007 __ mov(r2, Operand(offset)); |
971 __ RecordWrite(r0, r2, r1); | 1008 __ RecordWrite(r0, r2, r1); |
972 __ bind(&exit); | 1009 __ bind(&exit); |
973 if (expr->context() != Expression::kEffect && | 1010 if (context != Expression::kEffect && |
974 expr->context() != Expression::kValue) { | 1011 context != Expression::kValue) { |
975 Move(expr->context(), r3); | 1012 Move(context, r3); |
976 } | 1013 } |
977 break; | 1014 break; |
978 } | 1015 } |
979 | 1016 |
980 case Slot::LOOKUP: | 1017 case Slot::LOOKUP: |
981 UNREACHABLE(); | 1018 UNREACHABLE(); |
982 break; | 1019 break; |
983 } | 1020 } |
984 } | 1021 } |
985 } | 1022 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 } | 1055 } |
1019 | 1056 |
1020 | 1057 |
1021 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 1058 void FastCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
1022 // Assignment to a property, using a keyed store IC. | 1059 // Assignment to a property, using a keyed store IC. |
1023 | 1060 |
1024 // If the assignment starts a block of assignments to the same object, | 1061 // If the assignment starts a block of assignments to the same object, |
1025 // change to slow case to avoid the quadratic behavior of repeatedly | 1062 // change to slow case to avoid the quadratic behavior of repeatedly |
1026 // adding fast properties. | 1063 // adding fast properties. |
1027 if (expr->starts_initialization_block()) { | 1064 if (expr->starts_initialization_block()) { |
1028 // Reciever is under the key and value. | 1065 // Receiver is under the key and value. |
1029 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); | 1066 __ ldr(ip, MemOperand(sp, 2 * kPointerSize)); |
1030 __ push(ip); | 1067 __ push(ip); |
1031 __ CallRuntime(Runtime::kToSlowProperties, 1); | 1068 __ CallRuntime(Runtime::kToSlowProperties, 1); |
1032 } | 1069 } |
1033 | 1070 |
1034 __ pop(r0); | 1071 __ pop(r0); |
1035 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 1072 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1036 __ Call(ic, RelocInfo::CODE_TARGET); | 1073 __ Call(ic, RelocInfo::CODE_TARGET); |
1037 | 1074 |
1038 // If the assignment ends an initialization block, revert to fast case. | 1075 // If the assignment ends an initialization block, revert to fast case. |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 // If location is value, it is already on the stack, | 1249 // If location is value, it is already on the stack, |
1213 // so nothing to do here. | 1250 // so nothing to do here. |
1214 } | 1251 } |
1215 | 1252 |
1216 // Call the construct call builtin that handles allocation and | 1253 // Call the construct call builtin that handles allocation and |
1217 // constructor invocation. | 1254 // constructor invocation. |
1218 SetSourcePosition(expr->position()); | 1255 SetSourcePosition(expr->position()); |
1219 | 1256 |
1220 // Load function, arg_count into r1 and r0. | 1257 // Load function, arg_count into r1 and r0. |
1221 __ mov(r0, Operand(arg_count)); | 1258 __ mov(r0, Operand(arg_count)); |
1222 // Function is in esp[arg_count + 1]. | 1259 // Function is in sp[arg_count + 1]. |
1223 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 1260 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
1224 | 1261 |
1225 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); | 1262 Handle<Code> construct_builtin(Builtins::builtin(Builtins::JSConstructCall)); |
1226 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); | 1263 __ Call(construct_builtin, RelocInfo::CONSTRUCT_CALL); |
1227 | 1264 |
1228 // Replace function on TOS with result in r0, or pop it. | 1265 // Replace function on TOS with result in r0, or pop it. |
1229 DropAndMove(expr->context(), r0); | 1266 DropAndMove(expr->context(), r0); |
1230 } | 1267 } |
1231 | 1268 |
1232 | 1269 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1395 } | 1432 } |
1396 | 1433 |
1397 default: | 1434 default: |
1398 UNREACHABLE(); | 1435 UNREACHABLE(); |
1399 } | 1436 } |
1400 } | 1437 } |
1401 | 1438 |
1402 | 1439 |
1403 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { | 1440 void FastCodeGenerator::VisitCountOperation(CountOperation* expr) { |
1404 Comment cmnt(masm_, "[ CountOperation"); | 1441 Comment cmnt(masm_, "[ CountOperation"); |
1405 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | |
1406 ASSERT(proxy->AsVariable() != NULL); | |
1407 ASSERT(proxy->AsVariable()->is_global()); | |
1408 | 1442 |
1409 Visit(proxy); | 1443 // Expression can only be a property, a global or a (parameter or local) |
| 1444 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. |
| 1445 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
| 1446 LhsKind assign_type = VARIABLE; |
| 1447 Property* prop = expr->expression()->AsProperty(); |
| 1448 // In case of a property we use the uninitialized expression context |
| 1449 // of the key to detect a named property. |
| 1450 if (prop != NULL) { |
| 1451 assign_type = (prop->key()->context() == Expression::kUninitialized) |
| 1452 ? NAMED_PROPERTY |
| 1453 : KEYED_PROPERTY; |
| 1454 } |
| 1455 |
| 1456 // Evaluate expression and get value. |
| 1457 if (assign_type == VARIABLE) { |
| 1458 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
| 1459 EmitVariableLoad(expr->expression()->AsVariableProxy()->var(), |
| 1460 Expression::kValue); |
| 1461 } else { |
| 1462 // Reserve space for result of postfix operation. |
| 1463 if (expr->is_postfix() && expr->context() != Expression::kEffect) { |
| 1464 ASSERT(expr->context() != Expression::kUninitialized); |
| 1465 __ mov(ip, Operand(Smi::FromInt(0))); |
| 1466 __ push(ip); |
| 1467 } |
| 1468 Visit(prop->obj()); |
| 1469 ASSERT_EQ(Expression::kValue, prop->obj()->context()); |
| 1470 if (assign_type == NAMED_PROPERTY) { |
| 1471 EmitNamedPropertyLoad(prop, Expression::kValue); |
| 1472 } else { |
| 1473 Visit(prop->key()); |
| 1474 ASSERT_EQ(Expression::kValue, prop->key()->context()); |
| 1475 EmitKeyedPropertyLoad(prop, Expression::kValue); |
| 1476 } |
| 1477 } |
| 1478 |
| 1479 // Convert to number. |
1410 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); | 1480 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); |
1411 | 1481 |
1412 switch (expr->context()) { | 1482 // Save result for postfix expressions. |
1413 case Expression::kUninitialized: | 1483 if (expr->is_postfix()) { |
1414 UNREACHABLE(); | 1484 switch (expr->context()) { |
1415 case Expression::kValue: // Fall through | 1485 case Expression::kUninitialized: |
1416 case Expression::kTest: // Fall through | 1486 UNREACHABLE(); |
1417 case Expression::kTestValue: // Fall through | 1487 case Expression::kEffect: |
1418 case Expression::kValueTest: | 1488 // Do not save result. |
1419 // Duplicate the result on the stack. | 1489 break; |
1420 __ push(r0); | 1490 case Expression::kValue: // Fall through |
1421 break; | 1491 case Expression::kTest: // Fall through |
1422 case Expression::kEffect: | 1492 case Expression::kTestValue: // Fall through |
1423 // Do not save result. | 1493 case Expression::kValueTest: |
1424 break; | 1494 // Save the result on the stack. If we have a named or keyed property |
| 1495 // we store the result under the receiver that is currently on top |
| 1496 // of the stack. |
| 1497 switch (assign_type) { |
| 1498 case VARIABLE: |
| 1499 __ push(r0); |
| 1500 break; |
| 1501 case NAMED_PROPERTY: |
| 1502 __ str(r0, MemOperand(sp, kPointerSize)); |
| 1503 break; |
| 1504 case KEYED_PROPERTY: |
| 1505 __ str(r0, MemOperand(sp, 2 * kPointerSize)); |
| 1506 break; |
| 1507 } |
| 1508 break; |
| 1509 } |
1425 } | 1510 } |
| 1511 |
1426 // Call runtime for +1/-1. | 1512 // Call runtime for +1/-1. |
1427 __ push(r0); | 1513 __ push(r0); |
1428 __ mov(ip, Operand(Smi::FromInt(1))); | 1514 __ mov(ip, Operand(Smi::FromInt(1))); |
1429 __ push(ip); | 1515 __ push(ip); |
1430 if (expr->op() == Token::INC) { | 1516 if (expr->op() == Token::INC) { |
1431 __ CallRuntime(Runtime::kNumberAdd, 2); | 1517 __ CallRuntime(Runtime::kNumberAdd, 2); |
1432 } else { | 1518 } else { |
1433 __ CallRuntime(Runtime::kNumberSub, 2); | 1519 __ CallRuntime(Runtime::kNumberSub, 2); |
1434 } | 1520 } |
1435 // Call Store IC. | |
1436 __ mov(r2, Operand(proxy->AsVariable()->name())); | |
1437 __ ldr(ip, CodeGenerator::GlobalObject()); | |
1438 __ push(ip); | |
1439 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); | |
1440 __ Call(ic, RelocInfo::CODE_TARGET); | |
1441 // Restore up stack after store IC. | |
1442 __ add(sp, sp, Operand(kPointerSize)); | |
1443 | 1521 |
1444 switch (expr->context()) { | 1522 // Store the value returned in r0. |
1445 case Expression::kUninitialized: | 1523 switch (assign_type) { |
1446 UNREACHABLE(); | 1524 case VARIABLE: |
1447 case Expression::kEffect: // Fall through | 1525 __ push(r0); |
1448 case Expression::kValue: | 1526 if (expr->is_postfix()) { |
1449 // Do nothing. Result in either on the stack for value context | 1527 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
1450 // or discarded for effect context. | 1528 Expression::kEffect); |
| 1529 // For all contexts except kEffect: We have the result on |
| 1530 // top of the stack. |
| 1531 if (expr->context() != Expression::kEffect) { |
| 1532 MoveTOS(expr->context()); |
| 1533 } |
| 1534 } else { |
| 1535 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), |
| 1536 expr->context()); |
| 1537 } |
1451 break; | 1538 break; |
1452 case Expression::kTest: | 1539 case NAMED_PROPERTY: { |
1453 __ pop(r0); | 1540 __ mov(r2, Operand(prop->key()->AsLiteral()->handle())); |
1454 TestAndBranch(r0, true_label_, false_label_); | 1541 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); |
1455 break; | 1542 __ Call(ic, RelocInfo::CODE_TARGET); |
1456 case Expression::kValueTest: { | 1543 if (expr->is_postfix()) { |
1457 Label discard; | 1544 __ Drop(1); // Result is on the stack under the receiver. |
1458 __ ldr(r0, MemOperand(sp)); | 1545 if (expr->context() != Expression::kEffect) { |
1459 TestAndBranch(r0, true_label_, &discard); | 1546 MoveTOS(expr->context()); |
1460 __ bind(&discard); | 1547 } |
1461 __ add(sp, sp, Operand(kPointerSize)); | 1548 } else { |
1462 __ b(false_label_); | 1549 DropAndMove(expr->context(), r0); |
| 1550 } |
1463 break; | 1551 break; |
1464 } | 1552 } |
1465 case Expression::kTestValue: { | 1553 case KEYED_PROPERTY: { |
1466 Label discard; | 1554 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
1467 __ ldr(r0, MemOperand(sp)); | 1555 __ Call(ic, RelocInfo::CODE_TARGET); |
1468 TestAndBranch(r0, &discard, false_label_); | 1556 if (expr->is_postfix()) { |
1469 __ bind(&discard); | 1557 __ Drop(2); // Result is on the stack under the key and the receiver. |
1470 __ add(sp, sp, Operand(kPointerSize)); | 1558 if (expr->context() != Expression::kEffect) { |
1471 __ b(true_label_); | 1559 MoveTOS(expr->context()); |
| 1560 } |
| 1561 } else { |
| 1562 DropAndMove(expr->context(), r0, 2); |
| 1563 } |
1472 break; | 1564 break; |
1473 } | 1565 } |
1474 } | 1566 } |
1475 } | 1567 } |
1476 | 1568 |
1477 | 1569 |
1478 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { | 1570 void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { |
1479 Comment cmnt(masm_, "[ BinaryOperation"); | 1571 Comment cmnt(masm_, "[ BinaryOperation"); |
1480 switch (expr->op()) { | 1572 switch (expr->op()) { |
1481 case Token::COMMA: | 1573 case Token::COMMA: |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1731 __ pop(result_register()); | 1823 __ pop(result_register()); |
1732 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); | 1824 ASSERT_EQ(1, kSmiTagSize + kSmiShiftSize); |
1733 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 1825 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
1734 __ add(pc, r1, Operand(masm_->CodeObject())); | 1826 __ add(pc, r1, Operand(masm_->CodeObject())); |
1735 } | 1827 } |
1736 | 1828 |
1737 | 1829 |
1738 #undef __ | 1830 #undef __ |
1739 | 1831 |
1740 } } // namespace v8::internal | 1832 } } // namespace v8::internal |
OLD | NEW |