| 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 |