Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 560 | 560 |
| 561 private: | 561 private: |
| 562 Major MajorKey() { return ToBoolean; } | 562 Major MajorKey() { return ToBoolean; } |
| 563 int MinorKey() { return 0; } | 563 int MinorKey() { return 0; } |
| 564 }; | 564 }; |
| 565 | 565 |
| 566 | 566 |
| 567 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and | 567 // ECMA-262, section 9.2, page 30: ToBoolean(). Pop the top of stack and |
| 568 // convert it to a boolean in the condition code register or jump to | 568 // convert it to a boolean in the condition code register or jump to |
| 569 // 'false_target'/'true_target' as appropriate. | 569 // 'false_target'/'true_target' as appropriate. |
| 570 void CodeGenerator::ToBoolean(JumpTarget* true_target, JumpTarget* false_target) { | 570 void CodeGenerator::ToBoolean(JumpTarget* true_target, |
| 571 JumpTarget* false_target) { | |
| 571 Comment cmnt(masm_, "[ ToBoolean"); | 572 Comment cmnt(masm_, "[ ToBoolean"); |
| 572 | 573 |
| 573 // The value to convert should be popped from the stack. | 574 // The value to convert should be popped from the stack. |
| 574 frame_->EmitPop(eax); | 575 frame_->EmitPop(eax); |
| 575 | 576 |
| 576 // Fast case checks. | 577 // Fast case checks. |
| 577 | 578 |
| 578 // 'false' => false. | 579 // 'false' => false. |
| 579 __ cmp(eax, Factory::false_value()); | 580 __ cmp(eax, Factory::false_value()); |
| 580 false_target->Branch(equal); | 581 false_target->Branch(equal); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags); | 769 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags); |
| 769 // Fetch the operands from the stack. | 770 // Fetch the operands from the stack. |
| 770 frame_->EmitPop(ebx); // get y | 771 frame_->EmitPop(ebx); // get y |
| 771 __ mov(eax, frame_->Top()); // get x | 772 __ mov(eax, frame_->Top()); // get x |
| 772 // Generate the inline part of the code. | 773 // Generate the inline part of the code. |
| 773 deferred->GenerateInlineCode(); | 774 deferred->GenerateInlineCode(); |
| 774 // Put result back on the stack. It seems somewhat weird to let | 775 // Put result back on the stack. It seems somewhat weird to let |
| 775 // the deferred code jump back before the assignment to the frame | 776 // the deferred code jump back before the assignment to the frame |
| 776 // top, but this is just to let the peephole optimizer get rid of | 777 // top, but this is just to let the peephole optimizer get rid of |
| 777 // more code. | 778 // more code. |
| 778 deferred->exit()->Bind(); | 779 deferred->BindExit(); |
| 779 __ mov(frame_->Top(), eax); | 780 __ mov(frame_->Top(), eax); |
| 780 } else { | 781 } else { |
| 781 // Call the stub and push the result to the stack. | 782 // Call the stub and push the result to the stack. |
| 782 GenericBinaryOpStub stub(op, overwrite_mode, flags); | 783 GenericBinaryOpStub stub(op, overwrite_mode, flags); |
| 783 frame_->CallStub(&stub, 2); | 784 frame_->CallStub(&stub, 2); |
| 784 frame_->EmitPush(eax); | 785 frame_->EmitPush(eax); |
| 785 } | 786 } |
| 786 } | 787 } |
| 787 | 788 |
| 788 | 789 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 953 case Token::ADD: { | 954 case Token::ADD: { |
| 954 DeferredCode* deferred = NULL; | 955 DeferredCode* deferred = NULL; |
| 955 if (!reversed) { | 956 if (!reversed) { |
| 956 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode); | 957 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode); |
| 957 } else { | 958 } else { |
| 958 deferred = new DeferredInlinedSmiAddReversed(this, int_value, | 959 deferred = new DeferredInlinedSmiAddReversed(this, int_value, |
| 959 overwrite_mode); | 960 overwrite_mode); |
| 960 } | 961 } |
| 961 frame_->EmitPop(eax); | 962 frame_->EmitPop(eax); |
| 962 __ add(Operand(eax), Immediate(value)); | 963 __ add(Operand(eax), Immediate(value)); |
| 963 deferred->enter()->Branch(overflow, not_taken); | 964 deferred->BranchTo(overflow); |
| 964 __ test(eax, Immediate(kSmiTagMask)); | 965 __ test(eax, Immediate(kSmiTagMask)); |
| 965 deferred->enter()->Branch(not_zero, not_taken); | 966 deferred->BranchTo(not_zero); |
| 966 deferred->exit()->Bind(); | 967 deferred->BindExit(); |
| 967 frame_->EmitPush(eax); | 968 frame_->EmitPush(eax); |
| 968 break; | 969 break; |
| 969 } | 970 } |
| 970 | 971 |
| 971 case Token::SUB: { | 972 case Token::SUB: { |
| 972 DeferredCode* deferred = NULL; | 973 DeferredCode* deferred = NULL; |
| 973 frame_->EmitPop(eax); | 974 frame_->EmitPop(eax); |
| 974 if (!reversed) { | 975 if (!reversed) { |
| 975 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); | 976 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); |
| 976 __ sub(Operand(eax), Immediate(value)); | 977 __ sub(Operand(eax), Immediate(value)); |
| 977 } else { | 978 } else { |
| 978 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode); | 979 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode); |
| 979 __ mov(edx, Operand(eax)); | 980 __ mov(edx, Operand(eax)); |
| 980 __ mov(eax, Immediate(value)); | 981 __ mov(eax, Immediate(value)); |
| 981 __ sub(eax, Operand(edx)); | 982 __ sub(eax, Operand(edx)); |
| 982 } | 983 } |
| 983 deferred->enter()->Branch(overflow, not_taken); | 984 deferred->BranchTo(overflow); |
| 984 __ test(eax, Immediate(kSmiTagMask)); | 985 __ test(eax, Immediate(kSmiTagMask)); |
| 985 deferred->enter()->Branch(not_zero, not_taken); | 986 deferred->BranchTo(not_zero); |
| 986 deferred->exit()->Bind(); | 987 deferred->BindExit(); |
| 987 frame_->EmitPush(eax); | 988 frame_->EmitPush(eax); |
| 988 break; | 989 break; |
| 989 } | 990 } |
| 990 | 991 |
| 991 case Token::SAR: { | 992 case Token::SAR: { |
| 992 if (reversed) { | 993 if (reversed) { |
| 993 frame_->EmitPop(eax); | 994 frame_->EmitPop(eax); |
| 994 frame_->EmitPush(Immediate(value)); | 995 frame_->EmitPush(Immediate(value)); |
| 995 frame_->EmitPush(eax); | 996 frame_->EmitPush(eax); |
| 996 GenericBinaryOperation(op, type, overwrite_mode); | 997 GenericBinaryOperation(op, type, overwrite_mode); |
| 997 } else { | 998 } else { |
| 998 int shift_value = int_value & 0x1f; // only least significant 5 bits | 999 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 999 DeferredCode* deferred = | 1000 DeferredCode* deferred = |
| 1000 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, | 1001 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, |
| 1001 overwrite_mode); | 1002 overwrite_mode); |
| 1002 frame_->EmitPop(eax); | 1003 frame_->EmitPop(eax); |
| 1003 __ test(eax, Immediate(kSmiTagMask)); | 1004 __ test(eax, Immediate(kSmiTagMask)); |
| 1004 deferred->enter()->Branch(not_zero, not_taken); | 1005 deferred->BranchTo(not_zero); |
| 1005 __ sar(eax, shift_value); | 1006 __ sar(eax, shift_value); |
| 1006 __ and_(eax, ~kSmiTagMask); | 1007 __ and_(eax, ~kSmiTagMask); |
| 1007 deferred->exit()->Bind(); | 1008 deferred->BindExit(); |
| 1008 frame_->EmitPush(eax); | 1009 frame_->EmitPush(eax); |
| 1009 } | 1010 } |
| 1010 break; | 1011 break; |
| 1011 } | 1012 } |
| 1012 | 1013 |
| 1013 case Token::SHR: { | 1014 case Token::SHR: { |
| 1014 if (reversed) { | 1015 if (reversed) { |
| 1015 frame_->EmitPop(eax); | 1016 frame_->EmitPop(eax); |
| 1016 frame_->EmitPush(Immediate(value)); | 1017 frame_->EmitPush(Immediate(value)); |
| 1017 frame_->EmitPush(eax); | 1018 frame_->EmitPush(eax); |
| 1018 GenericBinaryOperation(op, type, overwrite_mode); | 1019 GenericBinaryOperation(op, type, overwrite_mode); |
| 1019 } else { | 1020 } else { |
| 1020 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1021 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 1021 DeferredCode* deferred = | 1022 DeferredCode* deferred = |
| 1022 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, | 1023 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, |
| 1023 overwrite_mode); | 1024 overwrite_mode); |
| 1024 frame_->EmitPop(eax); | 1025 frame_->EmitPop(eax); |
| 1025 __ test(eax, Immediate(kSmiTagMask)); | 1026 __ test(eax, Immediate(kSmiTagMask)); |
| 1026 __ mov(ebx, Operand(eax)); | 1027 __ mov(ebx, Operand(eax)); |
| 1027 deferred->enter()->Branch(not_zero, not_taken); | 1028 deferred->BranchTo(not_zero); |
| 1028 __ sar(ebx, kSmiTagSize); | 1029 __ sar(ebx, kSmiTagSize); |
| 1029 __ shr(ebx, shift_value); | 1030 __ shr(ebx, shift_value); |
| 1030 __ test(ebx, Immediate(0xc0000000)); | 1031 __ test(ebx, Immediate(0xc0000000)); |
| 1031 deferred->enter()->Branch(not_zero, not_taken); | 1032 deferred->BranchTo(not_zero); |
| 1032 // tag result and store it in TOS (eax) | 1033 // tag result and store it in TOS (eax) |
| 1033 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 1034 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 1034 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); | 1035 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); |
| 1035 deferred->exit()->Bind(); | 1036 deferred->BindExit(); |
| 1036 frame_->EmitPush(eax); | 1037 frame_->EmitPush(eax); |
| 1037 } | 1038 } |
| 1038 break; | 1039 break; |
| 1039 } | 1040 } |
| 1040 | 1041 |
| 1041 case Token::SHL: { | 1042 case Token::SHL: { |
| 1042 if (reversed) { | 1043 if (reversed) { |
| 1043 frame_->EmitPop(eax); | 1044 frame_->EmitPop(eax); |
| 1044 frame_->EmitPush(Immediate(value)); | 1045 frame_->EmitPush(Immediate(value)); |
| 1045 frame_->EmitPush(eax); | 1046 frame_->EmitPush(eax); |
| 1046 GenericBinaryOperation(op, type, overwrite_mode); | 1047 GenericBinaryOperation(op, type, overwrite_mode); |
| 1047 } else { | 1048 } else { |
| 1048 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1049 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 1049 DeferredCode* deferred = | 1050 DeferredCode* deferred = |
| 1050 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, | 1051 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, |
| 1051 overwrite_mode); | 1052 overwrite_mode); |
| 1052 frame_->EmitPop(eax); | 1053 frame_->EmitPop(eax); |
| 1053 __ test(eax, Immediate(kSmiTagMask)); | 1054 __ test(eax, Immediate(kSmiTagMask)); |
| 1054 __ mov(ebx, Operand(eax)); | 1055 __ mov(ebx, Operand(eax)); |
| 1055 deferred->enter()->Branch(not_zero, not_taken); | 1056 deferred->BranchTo(not_zero); |
| 1056 __ sar(ebx, kSmiTagSize); | 1057 __ sar(ebx, kSmiTagSize); |
| 1057 __ shl(ebx, shift_value); | 1058 __ shl(ebx, shift_value); |
| 1058 __ lea(ecx, Operand(ebx, 0x40000000)); | 1059 __ lea(ecx, Operand(ebx, 0x40000000)); |
| 1059 __ test(ecx, Immediate(0x80000000)); | 1060 __ test(ecx, Immediate(0x80000000)); |
| 1060 deferred->enter()->Branch(not_zero, not_taken); | 1061 deferred->BranchTo(not_zero); |
| 1061 // tag result and store it in TOS (eax) | 1062 // tag result and store it in TOS (eax) |
| 1062 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 1063 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 1063 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); | 1064 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); |
| 1064 deferred->exit()->Bind(); | 1065 deferred->BindExit(); |
| 1065 frame_->EmitPush(eax); | 1066 frame_->EmitPush(eax); |
| 1066 } | 1067 } |
| 1067 break; | 1068 break; |
| 1068 } | 1069 } |
| 1069 | 1070 |
| 1070 case Token::BIT_OR: | 1071 case Token::BIT_OR: |
| 1071 case Token::BIT_XOR: | 1072 case Token::BIT_XOR: |
| 1072 case Token::BIT_AND: { | 1073 case Token::BIT_AND: { |
| 1073 DeferredCode* deferred = NULL; | 1074 DeferredCode* deferred = NULL; |
| 1074 if (!reversed) { | 1075 if (!reversed) { |
| 1075 deferred = new DeferredInlinedSmiOperation(this, op, int_value, | 1076 deferred = new DeferredInlinedSmiOperation(this, op, int_value, |
| 1076 overwrite_mode); | 1077 overwrite_mode); |
| 1077 } else { | 1078 } else { |
| 1078 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, | 1079 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, |
| 1079 overwrite_mode); | 1080 overwrite_mode); |
| 1080 } | 1081 } |
| 1081 frame_->EmitPop(eax); | 1082 frame_->EmitPop(eax); |
| 1082 __ test(eax, Immediate(kSmiTagMask)); | 1083 __ test(eax, Immediate(kSmiTagMask)); |
| 1083 deferred->enter()->Branch(not_zero, not_taken); | 1084 deferred->BranchTo(not_zero); |
| 1084 if (op == Token::BIT_AND) { | 1085 if (op == Token::BIT_AND) { |
| 1085 __ and_(Operand(eax), Immediate(value)); | 1086 __ and_(Operand(eax), Immediate(value)); |
| 1086 } else if (op == Token::BIT_XOR) { | 1087 } else if (op == Token::BIT_XOR) { |
| 1087 __ xor_(Operand(eax), Immediate(value)); | 1088 __ xor_(Operand(eax), Immediate(value)); |
| 1088 } else { | 1089 } else { |
| 1089 ASSERT(op == Token::BIT_OR); | 1090 ASSERT(op == Token::BIT_OR); |
| 1090 __ or_(Operand(eax), Immediate(value)); | 1091 __ or_(Operand(eax), Immediate(value)); |
| 1091 } | 1092 } |
| 1092 deferred->exit()->Bind(); | 1093 deferred->BindExit(); |
| 1093 frame_->EmitPush(eax); | 1094 frame_->EmitPush(eax); |
| 1094 break; | 1095 break; |
| 1095 } | 1096 } |
| 1096 | 1097 |
| 1097 default: { | 1098 default: { |
| 1098 if (!reversed) { | 1099 if (!reversed) { |
| 1099 frame_->EmitPush(Immediate(value)); | 1100 frame_->EmitPush(Immediate(value)); |
| 1100 } else { | 1101 } else { |
| 1101 frame_->EmitPop(eax); | 1102 frame_->EmitPop(eax); |
| 1102 frame_->EmitPush(Immediate(value)); | 1103 frame_->EmitPush(Immediate(value)); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1215 // Strict only makes sense for equality comparisons. | 1216 // Strict only makes sense for equality comparisons. |
| 1216 ASSERT(!strict || cc == equal); | 1217 ASSERT(!strict || cc == equal); |
| 1217 | 1218 |
| 1218 int int_value = Smi::cast(*value)->value(); | 1219 int int_value = Smi::cast(*value)->value(); |
| 1219 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); | 1220 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); |
| 1220 | 1221 |
| 1221 SmiComparisonDeferred* deferred = | 1222 SmiComparisonDeferred* deferred = |
| 1222 new SmiComparisonDeferred(this, cc, strict, int_value); | 1223 new SmiComparisonDeferred(this, cc, strict, int_value); |
| 1223 frame_->EmitPop(eax); | 1224 frame_->EmitPop(eax); |
| 1224 __ test(eax, Immediate(kSmiTagMask)); | 1225 __ test(eax, Immediate(kSmiTagMask)); |
| 1225 deferred->enter()->Branch(not_zero, not_taken); | 1226 deferred->BranchTo(not_zero); |
|
William Hesse
2008/12/16 09:10:54
Will conflict with my changes, I think
| |
| 1226 // Test smi equality by pointer comparison. | 1227 // Test smi equality by pointer comparison. |
| 1227 __ cmp(Operand(eax), Immediate(value)); | 1228 __ cmp(Operand(eax), Immediate(value)); |
| 1228 deferred->exit()->Bind(); | 1229 deferred->BindExit(); |
| 1229 cc_reg_ = cc; | 1230 cc_reg_ = cc; |
| 1230 } | 1231 } |
| 1231 | 1232 |
| 1232 | 1233 |
| 1233 class CallFunctionStub: public CodeStub { | 1234 class CallFunctionStub: public CodeStub { |
| 1234 public: | 1235 public: |
| 1235 explicit CallFunctionStub(int argc) : argc_(argc) { } | 1236 explicit CallFunctionStub(int argc) : argc_(argc) { } |
| 1236 | 1237 |
| 1237 void Generate(MacroAssembler* masm); | 1238 void Generate(MacroAssembler* masm); |
| 1238 | 1239 |
| (...skipping 1463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2702 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); | 2703 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); |
| 2703 | 2704 |
| 2704 // Load the literal at the ast saved index. | 2705 // Load the literal at the ast saved index. |
| 2705 int literal_offset = | 2706 int literal_offset = |
| 2706 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; | 2707 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; |
| 2707 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 2708 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
| 2708 | 2709 |
| 2709 // Check whether we need to materialize the RegExp object. | 2710 // Check whether we need to materialize the RegExp object. |
| 2710 // If so, jump to the deferred code. | 2711 // If so, jump to the deferred code. |
| 2711 __ cmp(ebx, Factory::undefined_value()); | 2712 __ cmp(ebx, Factory::undefined_value()); |
| 2712 deferred->enter()->Branch(equal, not_taken); | 2713 deferred->BranchTo(equal); |
| 2713 deferred->exit()->Bind(); | 2714 deferred->BindExit(); |
| 2714 | 2715 |
| 2715 // Push the literal. | 2716 // Push the literal. |
| 2716 frame_->EmitPush(ebx); | 2717 frame_->EmitPush(ebx); |
| 2717 } | 2718 } |
| 2718 | 2719 |
| 2719 | 2720 |
| 2720 // This deferred code stub will be used for creating the boilerplate | 2721 // This deferred code stub will be used for creating the boilerplate |
| 2721 // by calling Runtime_CreateObjectLiteral. | 2722 // by calling Runtime_CreateObjectLiteral. |
| 2722 // Each created boilerplate is stored in the JSFunction and they are | 2723 // Each created boilerplate is stored in the JSFunction and they are |
| 2723 // therefore context dependent. | 2724 // therefore context dependent. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2763 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); | 2764 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); |
| 2764 | 2765 |
| 2765 // Load the literal at the ast saved index. | 2766 // Load the literal at the ast saved index. |
| 2766 int literal_offset = | 2767 int literal_offset = |
| 2767 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; | 2768 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; |
| 2768 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 2769 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
| 2769 | 2770 |
| 2770 // Check whether we need to materialize the object literal boilerplate. | 2771 // Check whether we need to materialize the object literal boilerplate. |
| 2771 // If so, jump to the deferred code. | 2772 // If so, jump to the deferred code. |
| 2772 __ cmp(ebx, Factory::undefined_value()); | 2773 __ cmp(ebx, Factory::undefined_value()); |
| 2773 deferred->enter()->Branch(equal, not_taken); | 2774 deferred->BranchTo(equal); |
| 2774 deferred->exit()->Bind(); | 2775 deferred->BindExit(); |
| 2775 | 2776 |
| 2776 // Push the literal. | 2777 // Push the literal. |
| 2777 frame_->EmitPush(ebx); | 2778 frame_->EmitPush(ebx); |
| 2778 // Clone the boilerplate object. | 2779 // Clone the boilerplate object. |
| 2779 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); | 2780 frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1); |
| 2780 // Push the new cloned literal object as the result. | 2781 // Push the new cloned literal object as the result. |
| 2781 frame_->EmitPush(eax); | 2782 frame_->EmitPush(eax); |
| 2782 | 2783 |
| 2783 | 2784 |
| 2784 for (int i = 0; i < node->properties()->length(); i++) { | 2785 for (int i = 0; i < node->properties()->length(); i++) { |
| (...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3766 // Perform optimistic increment/decrement. | 3767 // Perform optimistic increment/decrement. |
| 3767 if (is_increment) { | 3768 if (is_increment) { |
| 3768 __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 3769 __ add(Operand(eax), Immediate(Smi::FromInt(1))); |
| 3769 } else { | 3770 } else { |
| 3770 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 3771 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); |
| 3771 } | 3772 } |
| 3772 | 3773 |
| 3773 // If the count operation didn't overflow and the result is a | 3774 // If the count operation didn't overflow and the result is a |
| 3774 // valid smi, we're done. Otherwise, we jump to the deferred | 3775 // valid smi, we're done. Otherwise, we jump to the deferred |
| 3775 // slow-case code. | 3776 // slow-case code. |
| 3776 deferred->enter()->Branch(overflow, not_taken); | 3777 deferred->BranchTo(overflow); |
| 3777 __ test(eax, Immediate(kSmiTagMask)); | 3778 __ test(eax, Immediate(kSmiTagMask)); |
| 3778 deferred->enter()->Branch(not_zero, not_taken); | 3779 deferred->BranchTo(not_zero); |
| 3779 | 3780 |
| 3780 // Store the new value in the target if not const. | 3781 // Store the new value in the target if not const. |
| 3781 deferred->exit()->Bind(); | 3782 deferred->BindExit(); |
| 3782 frame_->EmitPush(eax); // Push the new value to TOS | 3783 frame_->EmitPush(eax); // Push the new value to TOS |
| 3783 if (!is_const) target.SetValue(NOT_CONST_INIT); | 3784 if (!is_const) target.SetValue(NOT_CONST_INIT); |
| 3784 } | 3785 } |
| 3785 | 3786 |
| 3786 // Postfix: Discard the new value and use the old. | 3787 // Postfix: Discard the new value and use the old. |
| 3787 if (is_postfix) { | 3788 if (is_postfix) { |
| 3788 frame_->Drop(); | 3789 frame_->Drop(); |
| 3789 } | 3790 } |
| 3790 } | 3791 } |
| 3791 | 3792 |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4087 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); | 4088 __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); |
| 4088 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); | 4089 __ cmp(ecx, FIRST_JS_OBJECT_TYPE); |
| 4089 false_target()->Branch(less); | 4090 false_target()->Branch(less); |
| 4090 __ cmp(ecx, LAST_JS_OBJECT_TYPE); | 4091 __ cmp(ecx, LAST_JS_OBJECT_TYPE); |
| 4091 cc_reg_ = less_equal; | 4092 cc_reg_ = less_equal; |
| 4092 | 4093 |
| 4093 } else { | 4094 } else { |
| 4094 // Uncommon case: typeof testing against a string literal that is | 4095 // Uncommon case: typeof testing against a string literal that is |
| 4095 // never returned from the typeof operator. | 4096 // never returned from the typeof operator. |
| 4096 false_target()->Jump(); | 4097 false_target()->Jump(); |
| 4097 // TODO(): Can this cause a problem because it is an expression that | |
| 4098 // exits without a virtual frame in place? | |
| 4099 } | 4098 } |
| 4100 return; | 4099 return; |
| 4101 } | 4100 } |
| 4102 | 4101 |
| 4103 Condition cc = no_condition; | 4102 Condition cc = no_condition; |
| 4104 bool strict = false; | 4103 bool strict = false; |
| 4105 switch (op) { | 4104 switch (op) { |
| 4106 case Token::EQ_STRICT: | 4105 case Token::EQ_STRICT: |
| 4107 strict = true; | 4106 strict = true; |
| 4108 // Fall through | 4107 // Fall through |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4388 // leave result in register eax. | 4387 // leave result in register eax. |
| 4389 | 4388 |
| 4390 // Prepare the smi check of both operands by or'ing them together | 4389 // Prepare the smi check of both operands by or'ing them together |
| 4391 // before checking against the smi mask. | 4390 // before checking against the smi mask. |
| 4392 __ mov(ecx, Operand(ebx)); | 4391 __ mov(ecx, Operand(ebx)); |
| 4393 __ or_(ecx, Operand(eax)); | 4392 __ or_(ecx, Operand(eax)); |
| 4394 | 4393 |
| 4395 switch (op_) { | 4394 switch (op_) { |
| 4396 case Token::ADD: | 4395 case Token::ADD: |
| 4397 __ add(eax, Operand(ebx)); // add optimistically | 4396 __ add(eax, Operand(ebx)); // add optimistically |
| 4398 enter()->Branch(overflow, not_taken); | 4397 BranchTo(overflow); |
| 4399 break; | 4398 break; |
| 4400 | 4399 |
| 4401 case Token::SUB: | 4400 case Token::SUB: |
| 4402 __ sub(eax, Operand(ebx)); // subtract optimistically | 4401 __ sub(eax, Operand(ebx)); // subtract optimistically |
| 4403 enter()->Branch(overflow, not_taken); | 4402 BranchTo(overflow); |
| 4404 break; | 4403 break; |
| 4405 | 4404 |
| 4406 case Token::DIV: | 4405 case Token::DIV: |
| 4407 case Token::MOD: | 4406 case Token::MOD: |
| 4408 // Sign extend eax into edx:eax. | 4407 // Sign extend eax into edx:eax. |
| 4409 __ cdq(); | 4408 __ cdq(); |
| 4410 // Check for 0 divisor. | 4409 // Check for 0 divisor. |
| 4411 __ test(ebx, Operand(ebx)); | 4410 __ test(ebx, Operand(ebx)); |
| 4412 enter()->Branch(zero, not_taken); | 4411 BranchTo(zero); |
| 4413 break; | 4412 break; |
| 4414 | 4413 |
| 4415 default: | 4414 default: |
| 4416 // Fall-through to smi check. | 4415 // Fall-through to smi check. |
| 4417 break; | 4416 break; |
| 4418 } | 4417 } |
| 4419 | 4418 |
| 4420 // Perform the actual smi check. | 4419 // Perform the actual smi check. |
| 4421 ASSERT(kSmiTag == 0); // adjust zero check if not the case | 4420 ASSERT(kSmiTag == 0); // adjust zero check if not the case |
| 4422 __ test(ecx, Immediate(kSmiTagMask)); | 4421 __ test(ecx, Immediate(kSmiTagMask)); |
| 4423 enter()->Branch(not_zero, not_taken); | 4422 BranchTo(not_zero); |
| 4424 | 4423 |
| 4425 switch (op_) { | 4424 switch (op_) { |
| 4426 case Token::ADD: | 4425 case Token::ADD: |
| 4427 case Token::SUB: | 4426 case Token::SUB: |
| 4428 // Do nothing here. | 4427 // Do nothing here. |
| 4429 break; | 4428 break; |
| 4430 | 4429 |
| 4431 case Token::MUL: | 4430 case Token::MUL: |
| 4432 // If the smi tag is 0 we can just leave the tag on one operand. | 4431 // If the smi tag is 0 we can just leave the tag on one operand. |
| 4433 ASSERT(kSmiTag == 0); // adjust code below if not the case | 4432 ASSERT(kSmiTag == 0); // adjust code below if not the case |
| 4434 // Remove tag from one of the operands (but keep sign). | 4433 // Remove tag from one of the operands (but keep sign). |
| 4435 __ sar(eax, kSmiTagSize); | 4434 __ sar(eax, kSmiTagSize); |
| 4436 // Do multiplication. | 4435 // Do multiplication. |
| 4437 __ imul(eax, Operand(ebx)); // multiplication of smis; result in eax | 4436 __ imul(eax, Operand(ebx)); // multiplication of smis; result in eax |
| 4438 // Go slow on overflows. | 4437 // Go slow on overflows. |
| 4439 enter()->Branch(overflow, not_taken); | 4438 BranchTo(overflow); |
| 4440 // Check for negative zero result. Use ecx = x | y. | 4439 // Check for negative zero result. Use ecx = x | y. NegativeZeroTest |
| 4441 __ NegativeZeroTest(generator(), eax, ecx, enter()); | 4440 // must be called after the deferred code has already been branched to |
| 4441 // via BranchTo, because NegativeZeroTest will not set the entry frame | |
| 4442 // or register file for the deferred code. | |
| 4443 __ NegativeZeroTest(eax, ecx, enter()); | |
| 4442 break; | 4444 break; |
| 4443 | 4445 |
| 4444 case Token::DIV: | 4446 case Token::DIV: |
| 4445 // Divide edx:eax by ebx. | 4447 // Divide edx:eax by ebx. |
| 4446 __ idiv(ebx); | 4448 __ idiv(ebx); |
| 4447 // Check for the corner case of dividing the most negative smi | 4449 // Check for the corner case of dividing the most negative smi |
| 4448 // by -1. We cannot use the overflow flag, since it is not set | 4450 // by -1. We cannot use the overflow flag, since it is not set |
| 4449 // by idiv instruction. | 4451 // by idiv instruction. |
| 4450 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 4452 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 4451 __ cmp(eax, 0x40000000); | 4453 __ cmp(eax, 0x40000000); |
| 4452 enter()->Branch(equal); | 4454 BranchTo(equal); |
| 4453 // Check for negative zero result. Use ecx = x | y. | 4455 // Check for negative zero result. Use ecx = x | y. NegativeZeroTest |
| 4454 __ NegativeZeroTest(generator(), eax, ecx, enter()); | 4456 // must be called after the deferred code has already been branched to |
| 4457 // via BranchTo, because NegativeZeroTest will not set the entry frame | |
| 4458 // or register file for the deferred code. | |
| 4459 __ NegativeZeroTest(eax, ecx, enter()); | |
| 4455 // Check that the remainder is zero. | 4460 // Check that the remainder is zero. |
| 4456 __ test(edx, Operand(edx)); | 4461 __ test(edx, Operand(edx)); |
| 4457 enter()->Branch(not_zero); | 4462 BranchTo(not_zero); |
| 4458 // Tag the result and store it in register eax. | 4463 // Tag the result and store it in register eax. |
| 4459 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 4464 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 4460 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); | 4465 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); |
| 4461 break; | 4466 break; |
| 4462 | 4467 |
| 4463 case Token::MOD: | 4468 case Token::MOD: |
| 4464 // Divide edx:eax by ebx. | 4469 // Divide edx:eax by ebx. |
| 4465 __ idiv(ebx); | 4470 __ idiv(ebx); |
| 4466 // Check for negative zero result. Use ecx = x | y. | 4471 // Check for negative zero result. Use ecx = x | y. NegativeZeroTest |
| 4467 __ NegativeZeroTest(generator(), edx, ecx, enter()); | 4472 // must be called after the deferred code has already been branched to |
| 4473 // via BranchTo, because NegativeZeroTest will not set the entry frame | |
| 4474 // or register file for the deferred code. | |
| 4475 __ NegativeZeroTest(edx, ecx, enter()); | |
| 4468 // Move remainder to register eax. | 4476 // Move remainder to register eax. |
| 4469 __ mov(eax, Operand(edx)); | 4477 __ mov(eax, Operand(edx)); |
| 4470 break; | 4478 break; |
| 4471 | 4479 |
| 4472 case Token::BIT_OR: | 4480 case Token::BIT_OR: |
| 4473 __ or_(eax, Operand(ebx)); | 4481 __ or_(eax, Operand(ebx)); |
| 4474 break; | 4482 break; |
| 4475 | 4483 |
| 4476 case Token::BIT_AND: | 4484 case Token::BIT_AND: |
| 4477 __ and_(eax, Operand(ebx)); | 4485 __ and_(eax, Operand(ebx)); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 4497 break; | 4505 break; |
| 4498 case Token::SHR: | 4506 case Token::SHR: |
| 4499 __ shr(eax); | 4507 __ shr(eax); |
| 4500 // Check that the *unsigned* result fits in a smi. | 4508 // Check that the *unsigned* result fits in a smi. |
| 4501 // Neither of the two high-order bits can be set: | 4509 // Neither of the two high-order bits can be set: |
| 4502 // - 0x80000000: high bit would be lost when smi tagging. | 4510 // - 0x80000000: high bit would be lost when smi tagging. |
| 4503 // - 0x40000000: this number would convert to negative when | 4511 // - 0x40000000: this number would convert to negative when |
| 4504 // Smi tagging these two cases can only happen with shifts | 4512 // Smi tagging these two cases can only happen with shifts |
| 4505 // by 0 or 1 when handed a valid smi. | 4513 // by 0 or 1 when handed a valid smi. |
| 4506 __ test(eax, Immediate(0xc0000000)); | 4514 __ test(eax, Immediate(0xc0000000)); |
| 4507 enter()->Branch(not_zero, not_taken); | 4515 BranchTo(not_zero); |
| 4508 break; | 4516 break; |
| 4509 case Token::SHL: | 4517 case Token::SHL: |
| 4510 __ shl(eax); | 4518 __ shl(eax); |
| 4511 // Check that the *signed* result fits in a smi. | 4519 // Check that the *signed* result fits in a smi. |
| 4512 __ lea(ecx, Operand(eax, 0x40000000)); | 4520 __ lea(ecx, Operand(eax, 0x40000000)); |
| 4513 __ test(ecx, Immediate(0x80000000)); | 4521 __ test(ecx, Immediate(0x80000000)); |
| 4514 enter()->Branch(not_zero, not_taken); | 4522 BranchTo(not_zero); |
| 4515 break; | 4523 break; |
| 4516 default: | 4524 default: |
| 4517 UNREACHABLE(); | 4525 UNREACHABLE(); |
| 4518 } | 4526 } |
| 4519 // Tag the result and store it in register eax. | 4527 // Tag the result and store it in register eax. |
| 4520 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 4528 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 4521 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); | 4529 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); |
| 4522 break; | 4530 break; |
| 4523 | 4531 |
| 4524 default: | 4532 default: |
| (...skipping 1167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5692 | 5700 |
| 5693 // Slow-case: Go through the JavaScript implementation. | 5701 // Slow-case: Go through the JavaScript implementation. |
| 5694 __ bind(&slow); | 5702 __ bind(&slow); |
| 5695 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 5703 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 5696 } | 5704 } |
| 5697 | 5705 |
| 5698 | 5706 |
| 5699 #undef __ | 5707 #undef __ |
| 5700 | 5708 |
| 5701 } } // namespace v8::internal | 5709 } } // namespace v8::internal |
| OLD | NEW |